对于给定的代码,我收到以下 SQL 错误。
You have an error in your SQL syntax; check the manual that coresponds to your MySQL server version for the right syntax to use near '' at line 1
代码:
$set_query = "";
foreach ($passed_columns as $c)
{
$set_query .= $c . " = " . ':' . $c . ',';
}
$p = strlen($set_query);
$set_query[$p-1] = "";
$SQL = 'UPDATE users SET ' . $set_query . ' WHERE user_id IN (' . implode(",", $_POST['user_id']) . ')';
$stmt = $dbh->prepare($SQL);
foreach($_POST['cols'] as $key => $val)
{
$stmt->bindValue(':' . $key, $val);
}
if (!$stmt->execute()) {
die(print_r($stmt->errorInfo()));
}
$_POST['cols'] 包含(column_name => 新列值)的键值数组。 $passed_columns 仅包含与 $_POST['cols'] 中的键匹配的列名数组
我认为这个问题与值的绑定(bind)方式有关。如果我回显 $SQL 变量,则输出是有效的 SQL(具有我正在测试的值)。
但奇怪的是,如果我手动将 $SQL 设置为它刚刚输出的有效 SQL(“UPDATE users SET role = :role WHERE user_id IN (100)”),脚本就可以运行。
最佳答案
反馈:
使用
“字符串”。 $var
很快就变得不可读了。 PHP 可以直接在字符串中嵌入变量:"string $var"
如果你需要做数组表达式,你可以使用大括号,比如"string {$arr['key']}"
.我建议用反引号分隔列名。
从设置列表中删除最后一个逗号是笨拙的。最好将集合列表构建为数组并使用逗号内爆。
您的 IN 列表容易受到 SQL 注入(inject)攻击。使用 (int) 映射 user_id 值以删除可能的恶意内容。如果 user_id 值不是整数,则使用查询参数(但不要在单个语句中混合使用
?
位置参数和命名参数——这会混淆 PDO)。bind_param() 是不必要的。只需将参数值传递给 execute()。在现代版本的 PHP 中,键值中的前导冒号是不必要的,这使得直接从键/值数组传递参数变得更加简单。
从您的示例中不清楚 $passed_columns 是从用户输入中获取的内容,还是硬编码在您的应用中。小心以这种方式引入 SQL 注入(inject)。我假设 $passed_columns 仅包含您控制的值。
prepare() 在出错时返回
false
,因此您应该始终检查其返回值并适本地响应错误。print_r()实际上打印到输出,而不是返回一个字符串,除非您传递可选的第二个参数 true。
令大多数 PHP 开发人员感到惊讶的是,双引号字符串实际上比单引号字符串快一点。不管怎样,差异都非常小,但是双引号字符串允许您将变量直接放在字符串中,为什么不呢?
下面是我将如何编写代码:
$set_terms = array();
foreach ($passed_columns as $c)
{
$set_terms[] = "`$c` = :$c";
}
$set_clause = implode(",", $set_terms);
$user_id_list = implode(",", array_map(function($id) { return (int) $id; },
$_POST["user_id"]);
$SQL = "UPDATE users SET {$set_clause} WHERE user_id IN ({$user_id_list})";
if (!($stmt = $dbh->prepare($SQL)) {
die(print_r($dbh->errorInfo(), true));
}
if (!$stmt->execute($_POST["cols"])) {
die(print_r($stmt->errorInfo(), true));
}
PS:如果出现错误,只使用 die() 可能不是最好的做法。专业的 Web 界面会为开发人员记录错误,然后向用户呈现更好的屏幕。
关于php - PDO 绑定(bind)问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16616254/