Php 警告:mysqli_stmt::close():无法在Y行的X中获取mysqli_stmt

Php 警告:mysqli_stmt::close():无法在Y行的X中获取mysqli_stmt,php,mysqli,Php,Mysqli,我对php编码相当陌生,自己解决了很多问题,但有一个问题我无法解决 $prep_stmt = "SELECT id FROM members WHERE Email = ? LIMIT 1"; $stmt = $mysqli->prepare($prep_stmt); // check existing Email if ($stmt) { $stmt->bind_param('s', $Email); $stmt->execute(); $stmt-

我对php编码相当陌生,自己解决了很多问题,但有一个问题我无法解决

$prep_stmt = "SELECT id FROM members WHERE Email = ? LIMIT 1";
$stmt = $mysqli->prepare($prep_stmt);

// check existing Email
if ($stmt) {
    $stmt->bind_param('s', $Email);
    $stmt->execute();
    $stmt->store_result();

    if ($stmt->num_rows == 1) {
        // A user with this Email address already exists
        $error_msg .= '<p class="error">A user with this Email address already exists.</p>';
        $stmt->close();
    }
            $stmt->close();
} else {
    $error_msg .= '<p class="error">Database error Line 39</p>';
            $stmt->close();
}
我猜代码无法到达第二个$stmt->close;在上面的代码中,if后面的代码位于if内部


我如何解决这个问题?是$stmt->close;真的需要吗?

为什么不在第二个if语句中删除第一个呢?还可以删除else语句中的close,因为您已检查$stmt是否为合法对象。基本上你说的是:$stmt不是合法对象,关闭它。但是关闭什么

这在两种情况下都有效:

$prep_stmt = "SELECT id FROM members WHERE Email = ? LIMIT 1";
$stmt = $mysqli->prepare($prep_stmt);

// check existing Email
if ($stmt) {
    $stmt->bind_param('s', $Email);
    $stmt->execute();
    $stmt->store_result();

    if ($stmt->num_rows == 1) {
        // A user with this Email address already exists
        $error_msg .= '<p class="error">A user with this Email address already exists.</p>';
        //Remove this one: $stmt->close();
    }
    $stmt->close();
} else {
    $error_msg .= '<p class="error">Database error Line 39</p>';
    //This one can be removed because $stmt isn't a legal object: $stmt->close();
}
您应该在执行后放入存储结果,如下所示:

$stmt->execute();
$stmt->store_result();
如果创建方法并传递查询,则该查询不起作用

只需删除if语句和close方法调用即可。为什么要将其添加到代码中

出现此错误的原因是您试图在语句创建失败时关闭语句。无法关闭从未创建过的对象。如果prepare调用失败,并且您的错误报告处于静默状态,则此函数将返回false而不是对象

如果启用正确的错误报告,则不应使用If语句。看

以下是您的代码的外观:

$prep_stmt = "SELECT id FROM members WHERE Email = ? LIMIT 1";
$stmt = $mysqli->prepare($prep_stmt);

// check existing Email
$stmt->bind_param('s', $Email);
$stmt->execute();
$result = $stmt->get_result();

if ($result->fetch_assoc()) {
    // A user with this Email address already exists
    $error_msg .= '<p class="error">A user with this Email address already exists.</p>';
}
尽量避免存储结果。如果启用错误报告,则没有理由使用任何if语句。否则,您将需要在这样的语句中包装每一行,因为这些调用中的任何一个都可能失败:prepare、bind_param、execute

如果获取所有结果,则无需关闭语句。当您调用get_result时,您将从MySQL获取所有内容


保持简单,不要添加不必要的代码。

您可以将该代码包装在else{}块中,但老实说,对$stmt->close的显式调用可能都不是必需的。PHP会自己清理它们。@MichaelBerkowski,所以移除它们是安全的吗?请发表一个答案,这样我可以给一些代表:可能。如果有要提取的行,则释放RDBMS以执行新查询,但如果您不打算在此脚本中发出新查询,则这不是问题,因为PHP将在脚本终止时清除这些行。另外,如果我没记错的话,调用store_result无论如何都可以避免这个问题。特别是,DB error块中的最后一个$stmt->close永远不会成功执行,因为$stmt不是对象。一定要删除它,因为它会导致致命错误。