难以理解如何获取新插入行的ID。
下面是我的过程化mysqli连接和SQL INSERT语句:
class DB {
var $conn;
function __construct($servername, $username, $password, $dbname, $dbport = 0000) {
$this->conn = new mysqli($servername, $username, $password, $dbname, $dbport );
}
// Run a query
public function query($sql) {
return $this->conn->query($sql);
}
// Clean incoming data
public function clean($data) {
return $this->conn->real_escape_string($data);
}
}
define("DB_HOST","localhost");
define("DB_USER","myusername");
define("DB_PASS","mypass");
define("DB_NAME","mydbname");
define("db",new DB(DB_HOST, DB_USER, DB_PASS, DB_NAME));
$sql = db->query("INSERT INTO my_table (field_one, field_two, field_three) VALUES ( 'test1', 'test2', 'test3')");
字符串
我想我可以做一些事情(like this):
if (mysqli_query(db, $sql)) {
$last_id = mysqli_insert_id(db);
echo "New record created. Last inserted ID is: " . $last_id;
} else {
echo "Error: " . $sql . "<br>" . mysqli_error(db);
}
型
错误消息:
Fatal error: Uncaught TypeError: mysqli_query(): Argument #1 ($mysql) must be of type mysqli, DB given in /var/www/vhosts/***.****.com/httpdocs/admin/test.php:36
Stack trace: #0 /var/www/vhosts/***.****.com/httpdocs/admin/test.php(36): mysqli_query() #1 {main} thrown in /var/www/vhosts/***.****.com/httpdocs/admin/test.php on line 36 line 36
型
这将是第二个块的第一行:if (mysqli_query(db, $sql)) {
**我哪里错了?**真的很感激你的解释w/什么和为什么?
这也可能是一个愚蠢的问题,但在我在网上读到的例子中--没有一个与我的连接设置完全匹配--没有一个提到ID的列名是否重要?我的格式是“table_id”,而不仅仅是“id”,而且它被设置为自动增量。
2条答案
按热度按时间b4wnujal1#
如果你真的包含了错误信息,那将是很有帮助的,但是问题是你的DB类既不是Mysqli类的扩展,也没有实现相关的接口,因此你不能简单地将它放入需要Mysqli对象的函数中。正如ADyson已经提到的,你的 Package 类是不必要的,并且会在这里积极地妨碍你,因为它会在很多其他地方。
抛弃 Package 类,直接使用Mysqli对象。
此外,全局状态通常是一个坏主意,特别是对于数据库连接。它允许“幽灵般的远程操作”,也就是看起来完全不相关的代码,通过全局命名空间中的共享对象产生副作用,以及将您束缚在只能使用单个数据库连接而无需进行重大重写。
通常,最好将DB连接传递到需要它的调用或对象中,例如:
字符串
wpcxdonn2#
不幸的是,无论下面的更改如何,您的代码都注定会失败,但是让我先解释一下为什么您会遇到这个问题,然后再解释为什么这仍然不起作用。
错误
您的
DB
类不是mysqli
的类型,但可以通过将class DB
更改为:字符串
以下是正在发生的事情的细分:
型
问题是
mysqli_query
期望以下内容:型
正如您所看到的,第一个参数需要类型
mysqli
,无论是直接用new mysqli()
示例化还是间接用extends mysqli
示例化。在DB
内部示例化new mysqli
的事实并没有什么不同,你可以复制整个mysqli
类,但是如果你命名它为DB
,它仍然会以那种方式输入,而没有扩展名。一旦你做了这个改变,你的论点应该被接受。
问题
潜在的问题是
DB
类仍然不适合执行mysqli
类代码。如果你看一下mysqli class docs,你会注意到你的类没有被适当地设计来包含你的连接信息,并且最终会失败,因为你正在调用的函数不能访问
$conn
。你的 Package 器用于非常基本的用例来调用query()
和clean()
方法,但仅此而已。它实际上并没有注入父mysqli
类正常运行所需的必要信息。从技术上讲,您可以通过使用getter暴露
$conn
来解决这个问题:型
或者使用
__toString()
魔术方法,当您不调用其他方法(如db->query()
)时,该方法将始终将db
视为连接。型
然而,这似乎真的不切实际,除非您有某种理由隐藏
mysqli
的其余功能。Package 器
这将 * 几乎 * 适合于创建一个数据库 Package 器,其中包含与其自己的类中的
mysqli_query
等函数交互的逻辑,但它似乎不是您心目中的目标。Package 器是有用的,因为它允许你在一个地方实现逻辑。你正在使用这个类之外的函数,需要
mysqli
,所以在这种情况下它实际上并不能帮助你。然而,一个正确的例子可能是这样的:型
子类
以这种方式构建类的正确方法是将
__construct
参数注入到父类中,但由于您正在尝试调用$conn
的query()
方法,因此这也会导致数据库类的损坏示例。一个如何正确构建子类的例子看起来像这样:
型
我的建议是直接通过
$db = new mysqli()
创建一个示例,而不是通过任何这些抽象过程。虽然这种方式抽象类有它的用途,因为你仍然处于学习阶段,我认为它增加了额外的,不必要的复杂性。