关闭准备好的语句

Closing prepared statements

我知道关闭准备好的语句是a suggested thing to do

但是我有一个这样的PHP脚本:

$sql = "SELECT * FROM `mytable` WHERE ...";
$stmt = $dbh->stmt_init();

if($stmt->prepare($sql))
{
    $stmt->bind_param("s", $user);

    if($stmt->execute())
    {
        $result = $stmt->get_result();
        $stmt->close();
    } else
        header("Location: .?error=unknown");
} else
    header("Location: .?error=conn");

如果一切正常,语句就会关闭,但是当执行过程中出现问题时,它不会关闭。

我应该写

else {
    $stmt->close();
    header("Location: .?error=unknown");
}

else {
    $stmt->close();
    header("Location: .?error=conn");
}

或者,既然发生了错误,我不应该担心关闭语句?

或者我什至可以写:

$sql = "SELECT * FROM `mytable` WHERE ...";
$stmt = $dbh->stmt_init();

if($stmt->prepare($sql))
{
    $stmt->bind_param("s", $user);

    if($stmt->execute())
    {
        $result = $stmt->get_result();
    } else
        header("Location: .?error=unknown");
} else
    header("Location: .?error=conn");

/*some other code*/

$stmt->close; //close every statement at the very end of the script

还是在我使用完准备好的语句后立即关闭它们以避免任何类型的错误更好?

您的代码的问题不是 close() 的使用,而是未启用的错误报告。您必须启用 mysqli error reporting 然后您可以简化您的代码。

理想情况下,您的数据库操作应该包装在函数或方法中,这样您就不必担心关闭任何东西。它将自动为您关闭。

$sql = "SELECT * FROM `mytable` WHERE ...";
$stmt = $dbh->prepare($sql);
$stmt->bind_param("s", $user);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();

如果要将其包装在函数中,则不需要 close()

function getResults(\mysqli $dbh, string $sql, string $types, array $params): array {
    $stmt = $dbh->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
}

然后如果你有异常你应该创建一个generic错误处理程序,它会在错误发生时通过生成 HTTP 500 响应代码将用户重定向到 500 页面,并将将所有异常详细信息记录到服务器上的文件中。

不要关闭它。

尽管其他答案(10 年前写的)怎么说,但通常您不会关闭准备好的语句。只是没有必要。当当前作用域关闭时,它将自动关闭。这意味着即使在脚本执行期间您也不关心关闭语句,更不用说完全完成 PHP 脚本了——在这种情况下,整个数据库连接 将自动关闭,它也会释放所有相关资源。

附带说明一下,您为 运行 一个简单查询编写的代码几乎是所需代码的五倍。这是应该如何完成的,整洁简洁:

$sql = "SELECT * FROM `mytable` WHERE ...";
$stmt->prepare($sql);
$stmt->bind_param("s", $user);
$stmt->execute();
$result = $stmt->get_result();

事实是,您的数据库代码永远不应该报告它的错误。您的代码在其他地方应该有一个独特的部分,可以处理所有错误。

不,在应用程序错误的情况下进行 HTTP 重定向不是可行的方法。您的应用程序应该 return 一个正确的 HTTP 代码 (5xx) 来告诉客户端出现了问题。