我很好奇是否有可能使用PDO将值数组绑定到占位符。这里的用例试图传递一个值数组,以便与IN()条件一起使用。
我希望能够这样做:
<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN(:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>
并让PDO绑定并引用数组中的所有值。
目前我正在做:
<?php
$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
foreach($ids as &$val)
$val=$db->quote($val); //iterate through array and quote
$in = implode(',',$ids); //create comma separated list
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN('.$in.')'
);
$stmt->execute();
?>
这当然是工作,但只是想知道是否有一个内置的解决方案,我错过了?
因为我做了很多动态查询,所以这是我做的一个超级简单的helper函数。
public static function bindParamArray($prefix, $values, &$bindArray)
{
$str = "";
foreach($values as $index => $value){
$str .= ":".$prefix.$index.",";
$bindArray[$prefix.$index] = $value;
}
return rtrim($str,",");
}
像这样使用它:
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
返回一个字符串:id1,:id2,:id3,并更新你的$bindArray绑定,当你需要运行你的查询时。简单!
据我所知,没有任何可能将数组绑定到PDO语句中。
但有两种常见的解决方案:
使用位置占位符(?,?,?,?)或命名占位符(:id1,:id2,:id3)
在美元=内爆(',',array_fill (0, count ($ id), ' ? '));
之前引用数组
$where = array_map(数组($db, 'quote'), $ids);
这两种选择都是好的和安全的。
我更喜欢第二个,因为它更短,如果我需要它,我可以var_dump参数。
使用占位符,您必须绑定值,最终您的SQL代码将是相同的。
$sql = "SELECT * FROM table WHERE id IN ($whereIn)";
最后一个对我来说很重要的是避免错误“绑定变量的数量与标记的数量不匹配”
它是使用位置占位符的一个很好的例子,只是因为它对传入参数有内部控制。
您必须构造查询字符串。
<?php
$ids = array(1, 2, 3, 7, 8, 9);
$inQuery = implode(',', array_fill(0, count($ids), '?'));
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN(' . $inQuery . ')'
);
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
$stmt->bindValue(($k+1), $id);
$stmt->execute();
?>
chris(评论)和一些人都有麻烦了,建议foreach-loop…
(...)
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
$stmt->bindValue(($k+1), $id);
$stmt->execute();
... 可能是多余的,因此foreach循环和$stmt->执行可以被替换为…
<?php
(...)
$stmt->execute($ids);
使用IN语句有这么重要吗?尝试使用FIND_IN_SET操作。
例如,在PDO中有这样一个查询
SELECT * FROM table WHERE FIND_IN_SET(id, :array)
然后你只需要绑定一个数组的值,用逗号括起来,就像这个
$ids_string = implode(',', $array_of_smth); // WITHOUT WHITESPACES BEFORE AND AFTER THE COMMA
$stmt->bindParam('array', $ids_string);
做完了。
UPD:正如一些人在评论中指出的,有一些问题需要明确说明。
FIND_IN_SET没有在表中使用索引,而且它还没有实现——请参阅MYSQL错误跟踪器中的这条记录。感谢@BillKarwin的通知。
不能使用内部带有逗号的字符串作为数组的搜索值。这是不可能在内爆后以正确的方式解析这样的字符串,因为你使用逗号符号作为分隔符。感谢@VaL的提示。
总之,如果您不严重依赖索引,并且不使用带逗号的字符串进行搜索,那么我的解决方案将比上面列出的解决方案更容易、更简单、更快。
因为我做了很多动态查询,所以这是我做的一个超级简单的helper函数。
public static function bindParamArray($prefix, $values, &$bindArray)
{
$str = "";
foreach($values as $index => $value){
$str .= ":".$prefix.$index.",";
$bindArray[$prefix.$index] = $value;
}
return rtrim($str,",");
}
像这样使用它:
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
返回一个字符串:id1,:id2,:id3,并更新你的$bindArray绑定,当你需要运行你的查询时。简单!