开发者问题收集

结束准备好的声明

2020-04-20
1306

我知道关闭准备好的语句是 建议做的事情

但是我有一个这样的 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

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

2个回答

您的代码的问题不在于 close() 的使用,而在于未启用错误报告。您必须启用 mysqli 错误报告 ,然后才能简化代码。

您的 DB 操作最好包装在函数或方法中,然后您无需担心关闭任何东西。它会自动为您关闭。

$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);
}

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

Dharman
2020-04-20

不要关闭它。

尽管另一个答案(10 年前写的)说了什么,但一般来说,您不会关闭准备好的语句。这根本没有必要。当前范围关闭时,它将 自动关闭 。这意味着您甚至在脚本执行期间也不必关心关闭语句,更不用说完全完成 PHP 脚本了 - 在这种情况下, 整个数据库连接 将自动关闭,并且它还将释放所有相关资源。

顺便说一句,您编写的代码比运行简单查询所需的代码多出近五倍。下面是应该如何做,整洁而简洁:

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

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

不,在应用程序出错的情况下执行 HTTP 重定向并不是解决问题的办法。您的应用程序应该只返回正确的 HTTP 代码 (5xx) 来告知客户端出现了问题。

Your Common Sense
2020-04-20