3

最后开始学习准备好的陈述。尝试运行一对简单的插入时,我遇到了一个令人发狂的错误:

$p_stmt = $mysqli->prepare("INSERT INTO ww_pages (page_key) VALUES (?)");
$p_stmt->bind_param('s', $page_key);
$p_stmt->execute();
        
$pv_stmt = $mysqli->prepare("INSERT INTO ww_page_versions (page_id, page_title, page_content, version_notes, version_timestamp) VALUES (?, ?, ?, ?, ?)");
$pv_stmt->bind_param('issss', $p_stmt->insert_id, $page_title, trim($_POST["page_content"]), trim($_POST["version_notes"]), date("Y-m-d H:i:s"));
$pv_stmt->execute();
echo $pv_stmt->error;

给出了这个echo $pv_stmt->error;错误:Column 'page_id' cannot be null

正如我确定您可以解释的那样,我正在尝试分配page_idinsert_id一个语句。我 100% 确定这个值是非空的,并返回一个整数值。我直接用这个测试了它:

echo "NEW ID: ".$p_stmt->insert_id."::".is_int($p_stmt->insert_id);

输出?NEW ID: 13::1

我究竟做错了什么?当列不为空时,为什么我得到“列不能为空”?我可以在网上找到的唯一解决方案是涉及意外的空值。

4

2 回答 2

1

这个问题的解决方案是将属性的值保存$p_stmt->insert_id在一个变量中,然后绑定该变量。无论如何,您都必须这样做trim()date()尽管出于不同的原因。

$insert_id = $p_stmt->insert_id;
$page_content = trim($_POST["page_content"]);
$version_notes = trim($_POST["version_notes"]);
$date = date("Y-m-d H:i:s");
$pv_stmt->bind_param('issss', $insert_id, $page_title, $page_content, $version_notes, $date);

从 PHP 8.1 开始,当您将所有值作为数组传递给execute(). 不需要临时变量。

$pv_stmt = $mysqli->prepare("INSERT INTO ww_page_versions (page_id, page_title, page_content, version_notes, version_timestamp) VALUES (?, ?, ?, ?, ?)");
$pv_stmt->execute([$p_stmt->insert_id, $page_title, trim($_POST["page_content"]), trim($_POST["version_notes"]), date("Y-m-d H:i:s")]);

解释为什么绑定insert_id不起作用

mysqli_stmt::insert_id在 PHP 8.1 中,绑定产生值的原因NULL变得更加清晰。从这个版本开始,PHP 为大多数内置类添加了属性类型,即使对于不是真正的属性而是__get()调用的属性也是如此。使用 PHP 8.1,您会收到以下错误:

致命错误:未捕获错误:无法通过引用访问未初始化的不可空属性 mysqli_stmt::$insert_id

PHP 声称该属性未初始化,您不能引用未初始化的属性。您可以使用以下代码模仿相同的行为:

class A {
    public int $insert_id;
}

$a = new A();

$stmt = $mysqli->prepare('SELECT ?');
$stmt->bind_param('s', $a->insert_id);
$stmt->execute();

出于同样的原因,通过引用变量进行赋值是行不通的:

$foo =& $p_stmt->insert_id;

但是您可能会问,当您可以毫无问题地读取其值时,如何才能未初始化该属性。答案是因为这些属性在内部是使用 PHP 中的函数调用实现的,类似于__get()魔术方法。该值是从 mysqlnd 的内部存储器中读取的,而不是从属性本身中读取的。的属性mysqli只是底层客户端库 mysqlnd 的一个门面。

于 2022-02-19T12:39:01.297 回答
0

将 的值insert_id放入一个临时变量并绑定该变量。

$p_stmt = $mysqli->prepare("INSERT INTO ww_pages (page_key) VALUES (?)");
$p_stmt->bind_param('s', $page_key);
$p_stmt->execute();
$insert_id = $p_stmt->insert_id;

$pv_stmt = $mysqli->prepare("INSERT INTO ww_page_versions (page_id, page_title, page_content, version_notes, version_timestamp) VALUES (?, ?, ?, ?, ?)");
$pv_stmt->bind_param('issss', $insert_id, $page_title, trim($_POST["page_content"]), trim($_POST["version_notes"]), date("Y-m-d H:i:s"));
$pv_stmt->execute();
于 2013-10-08T17:36:36.200 回答