从 mysqli 转换为准备好的语句
Converting from mysqli to prepared statements
我正在尝试将代码从 mysqli_* 语句转换为准备好的语句以防止 SQL 注入。以下代码是我试图转换的代码(目前它可以正常工作):
$details = mysqli_query($linkDB,"SELECT * FROM ".PREFIX."Issues WHERE id='".$_POST['article']."' AND disabled='0' LIMIT 1");
$detail = mysqli_fetch_assoc($details);
这是我转换为准备好的语句的尝试。任何使它更简洁的方法都将不胜感激(因为我要从 2 行代码变成很多行):
$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);
}
}
以上代码没有 return/store $detail 变量中的 db 值,以便稍后在脚本中进行处理。我试过注释掉 mysqli_stmt_close($PRE) 调用,但这没有区别。感谢您的帮助!
如果您不是经验丰富的编码人员,我会推荐 PDO。它是面向对象的,适合现代编码方式 PHP。
在你的配置文件中你输入:
$db = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
还有你的脚本:
$statement = $pdo->prepare('SELECT * FROM '.PREFIX.'Issues WHERE id = :id AND disabled = 0 LIMIT 1';
$statement->execute(['id' => $_POST['article']);
$result = $statement->fetch(PDO::FETCH_ASSOC);
代码中的主要错误是查询中 '?'
的拼写错误。如果 ?
在引号内,它不会被视为占位符,而是被视为文字值。
使用 MySQLi 时,您应该 enable MySQLi exception mode。如果这样做,则不再需要检查每个函数的结果。您还应该使用 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();
我正在尝试将代码从 mysqli_* 语句转换为准备好的语句以防止 SQL 注入。以下代码是我试图转换的代码(目前它可以正常工作):
$details = mysqli_query($linkDB,"SELECT * FROM ".PREFIX."Issues WHERE id='".$_POST['article']."' AND disabled='0' LIMIT 1");
$detail = mysqli_fetch_assoc($details);
这是我转换为准备好的语句的尝试。任何使它更简洁的方法都将不胜感激(因为我要从 2 行代码变成很多行):
$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);
}
}
以上代码没有 return/store $detail 变量中的 db 值,以便稍后在脚本中进行处理。我试过注释掉 mysqli_stmt_close($PRE) 调用,但这没有区别。感谢您的帮助!
如果您不是经验丰富的编码人员,我会推荐 PDO。它是面向对象的,适合现代编码方式 PHP。
在你的配置文件中你输入:
$db = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
还有你的脚本:
$statement = $pdo->prepare('SELECT * FROM '.PREFIX.'Issues WHERE id = :id AND disabled = 0 LIMIT 1';
$statement->execute(['id' => $_POST['article']);
$result = $statement->fetch(PDO::FETCH_ASSOC);
代码中的主要错误是查询中 '?'
的拼写错误。如果 ?
在引号内,它不会被视为占位符,而是被视为文字值。
使用 MySQLi 时,您应该 enable MySQLi exception mode。如果这样做,则不再需要检查每个函数的结果。您还应该使用 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();