首页 > 解决方案 > 从 mysqli 转换为准备好的语句

问题描述

我正在尝试将代码从 mysqli_* 语句转换为准备好的语句以防止 SQL 注入。以下代码是我试图转换的(并且它目前可以正常工作):

$details = mysqli_query($linkDB,"SELECT * FROM ".PREFIX."Issues WHERE id='".$_POST['article']."' AND disabled='0' LIMIT 1");
$detail = mysqli_fetch_assoc($details);

这是我尝试转换为准备好的陈述。任何使这更简洁的方法都将不胜感激(因为我将从两行代码变为多行):

$SQL = "SELECT * FROM ".PREFIX."Issues WHERE id='?' AND disabled='0' LIMIT 1";
$PRE = mysqli_stmt_init($linkDB);
//if (! $PRE = mysqli_prepare($linkDB, $SQL)) {   (alt attempt)
    if (! mysqli_stmt_prepare($PRE, $SQL)) {
        echo "<f><msg>ERROR: Could not prepare query: ".$SQL.", ".mysqli_error($linkDB)."</msg></f>";
    } else {
        mysqli_stmt_bind_param($PRE, "i", $test);
        $test = $_POST['article'];
        if (! mysqli_stmt_execute($PRE)) {
            echo "<f><msg>ERROR: Could not execute query: ".$SQL.", ".mysqli_error($linkDB)."</msg></f>";
        } else{
            $details = mysqli_stmt_get_result($PRE);
            $detail = mysqli_fetch_assoc($details);
            mysqli_stmt_close($PRE);
        }
}

上面的代码不会在 $detail 变量中返回/存储 db 值,以便稍后在脚本中进行处理。我试过注释掉 mysqli_stmt_close($PRE) 调用,但这没有区别。我感谢您的帮助!

标签: phpmysqliprepared-statement

解决方案


您的代码中的主要错误是'?'您的查询中的拼写错误。如果?在引号内,则不将其视为占位符,而是将其视为文字值。

使用 MySQLi 时,您应该启用 MySQLi 异常模式。如果您这样做,则不再需要检查每个函数的结果。您还应该使用 OOP 样式,因为它不那么冗长,而且您不太可能犯愚蠢的错误。

// put this line before you open the MySQLi connection
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$stmt = $linkDB->prepare('SELECT * FROM '.PREFIX.'Issues WHERE id=? AND disabled=0 LIMIT 1');
$stmt->bind_param('i', $_POST['article']);
$stmt->execute();
$detail = $stmt->get_result()->fetch_assoc();

推荐阅读