PHP:mysqli_stmt->;close()影响stmt的早期副本
我正在制作一个函数,以便在sql查询中更轻松地使用准备好的语句。但是在工作中,我遇到了一个奇怪的错误。 当您在PHP:mysqli_stmt->;close()影响stmt的早期副本,php,mysqli,Php,Mysqli,我正在制作一个函数,以便在sql查询中更轻松地使用准备好的语句。但是在工作中,我遇到了一个奇怪的错误。 当您在$response的第一个var_dump下面运行代码时,会像我期望的那样打印$stmt变量,但在关闭$stmt后,它会发出大量警告并打印一个填充为空的$stmt版本。我只将$stmt复制为$response,因此我不希望在关闭$stmt时更改$response。 有人能解释一下为什么会发生这种情况,以及我如何预防它吗 function sql_bug() { global $d
$response
的第一个var_dump
下面运行代码时,会像我期望的那样打印$stmt
变量,但在关闭$stmt
后,它会发出大量警告并打印一个填充为空的$stmt
版本。我只将$stmt复制为$response
,因此我不希望在关闭$stmt
时更改$response
。
有人能解释一下为什么会发生这种情况,以及我如何预防它吗
function sql_bug() {
global $dbc; // Database connection
$sql = "UPDATE users SET username = 'J0R1AN' WHERE id = 1"; // Test query
if ($stmt = $dbc->prepare($sql)) {
if ($stmt->execute()) {
$response = $stmt->get_result();
if ($response === false) {
// Checks for e.g. UPDATE queries that return bool(false) instead of a mysqli_result,
// and sets $response to $stmt instead, to return more valuable information when using UPDATE
$response = $stmt;
}
var_dump($response); // Prints expected $stmt variable
$stmt->close(); // Somehow changes $response?
var_dump($response); // Prints $stmt variable filled with NULLS
return $response;
}
}
return false;
}
变量赋值不会在PHP中创建对象的新副本。要创建副本,您需要使用
clone
。简单的例子:
$obj = (object) ['a'=>42];
$new_obj = $obj;
$obj->a = 100;
var_dump($new_obj);
// outputs
// stdClass Object
// (
// [a] => 100
// )
你已经成为多个谬误的受害者
close
只会使很多事情复杂化prepare
或execute
函数的返回值。而是启用mysqli错误报告李>
mysqli\u stmt
或mysqli\u result
对象。执行语句并获取数据后,可以放弃它们function sql_bug(\mysqli $dbc, string $sql, array $params = []): ?array {
$stmt = $dbc->prepare($sql);
if ($params) {
// bind optional parameters if the query has variable input
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
$response = $stmt->get_result();
if ($response) {
// If the query returned results then fetch them into an array and return it
return $response->fetch_all(MYSQLI_BOTH);
}
// return nothing if the query was successfully executed and it didn't produce results
return null;
}
上述函数是一个通用函数,可以处理任何带参数和不带参数的SQL语句。如果查询是INSERT或UPDATE,它将不返回任何内容;如果查询是SELECT,它将返回数组中的数据。无需复制或返回内部对象。您正在编写一个函数来从mysqli内部进行抽象。您需要停止手动检查错误。请阅读:如果你关闭了这个物体,你希望发生什么?为什么要关闭它?“我只将$stmt复制为$response”-不,对象不会以这种方式复制。您需要使用
clone
来复制对象。很抱歉,我没有澄清,我关闭了该语句,因为我读到这是一个很好的做法,并让MySQL知道它可能会忘记该语句。我希望$response变量(当它仍然有内容时是$stmt的副本)保持不变,这样我可以在关闭原始$stmtOh后返回它并使用变量,我只说下一个注释,所以如果在对象上使用=
操作符,它不会复制它?谢谢编辑:当我在$stmt
变量上运行clone
时,我得到以下错误:致命错误:未捕获错误:尝试克隆mysqli\u stmt类的不可克隆对象
。我需要做些什么才能让它“可克隆”吗?谢谢你的评论,我从中学到了很多。但我希望函数具有的一个特性是返回$stmt变量,这样我就可以读取更新查询中受影响的_行。我会稍微修改一下你的代码,这样就不需要了。它也是mysqli对象的一个属性。请看一件事,当我执行sql查询,例如UPDATE,然后在sql\u bug()
函数本身echo$dbc->infected\u rows
时,我得到了预期的超过0个infected\u rows,但当我在函数外部执行相同的代码时,因此在调用sql\u bug()
后,我总是得到-1作为infected\u rows。在文档中,它说它将从上一个查询返回,但感觉好像我遇到了一些范围问题。我也没有给出错误,因为error
变量是空的,我的更新查询按预期工作,并且实际更改了values@J0R1AN请你把这个问题单独问一下好吗。使用此函数创建一个简单的可复制示例。