Closing prepared statements

£可爱£侵袭症+ 提交于 2020-06-26 05:06:09

问题


I know that closing prepared statements is a suggested thing to do.

But I have a PHP script like this:

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

The statement gets closed if everything is ok, but when something fails during the execution it doesn't get closed.

Should I write

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

and

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

or, since an error occurred, I shouldn't worry about closing the statement?

Or could I even write:

$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

or is it better to close the prepared statements right after I have finished using them to avoid any sort of bugs?


回答1:


The problem with your code is not the use of close(), but the error reporting, which is not enabled. You must enable mysqli error reporting and then you can simplify your code.

Your DB operations should ideally be wrapped in a function or a method and then you do not need to worry about closing anything. It will be closed for you automatically.

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

If you were to wrap it in a function, then there is no need for 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);
}

Then if you have an exception you should create a generic error handler, which will redirect the user to 500 page by generating HTTP 500 response code when an error happens, and will log all the exception details into a file on the server.




回答2:


Don't close it.

Despite what the other answer (written 10 years ago) says, as a rule you don't close a prepared statement. It's just not necessary. It will be closed automatically when the current scope will be closed. It means you don't care about closing the statement even during the script execution, let alone finishing the PHP script completely - in this case the entire database connection will be closed automatically, and it will free up all the associated resources as well.

On a side note, you are writing nearly five times more code to run a simple query than it needed. Here is how it should be done, tidy and concise:

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

The thing is, your database code should never ever report its errors. There should be a distinct part of your code elsewhere, that would take care of all errors.

And no, doing an HTTP redirect in case of the application error is not the way to go. Your application should just return a proper HTTP code (5xx) to tell the client there was a problem.



来源:https://stackoverflow.com/questions/61323391/closing-prepared-statements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!