我有以下代码:
$inputs = "1,2,3,4,5";
$sql = "SELECT * FROM obj WHERE id IN(:input)";
$commond = Yii::app()->db->createCommand($sql);
$commond->bindValue(":input", $inputs , PDO::PARAM_STR);
但是查询结果不正确。如何为这种IN
情况绑定参数?
现在像这样使用它
$command = Yii::app()->db->createCommand()
->select()
->from('tableName')
->where(array('in', 'id', explode(',', $inputs)));
我会尝试用$command->bindValue()
方法回来。
在我的项目中遇到过几次这个问题后,我想出了以下使用 CDbCriteria 的 Yii 解决方法,这有点 hacky,但提供了参数计数匹配的安全性。
当应用于您的示例时,我的代码将是:
$inputs = array(1,2,3,4,5);
$criteria = new CDbCriteria();
$criteria->addInCondition('id',$inputs);
$sql = 'SELECT * FROM obj WHERE '.$criteria->condition;
$command = Yii::app()->db->createCommand($sql);
$results = $command->queryAll(true, $criteria->params);
更新
Yii 内置了一种更简洁的方法来执行此操作:
$results = Yii::app()->db->createCommand()
->select()
->from('obj')
->where(['in', 'id', $inputs])
->queryAll();
查看文档
在 CDbCommand 中使用 Yii 的方法链接来构建您的查询(如 Uday Sawant 的回答)通常是一个不错的选择。如果必须逐个构建查询并不理想,一个很好的替代方法是展平参数数组,这样您就不会绕过 SQL 注入保护,如下所示:
$sql = "SELECT * FROM obj WHERE id IN (:id_array) AND other_field = :other_value";
$args = array(
'id_array' => array(1, 2, 3, 4, 5),
'other_value' => 12,
);
// Flatten array arguments into multiple parameters,
// replacing with parameter lists in the SQL
$newArgs = array();
$replace = array();
foreach($args as $oldKey => $input) {
if(!is_array($input)) {
$newArgs[$oldKey] = $args[$oldKey];
continue;
}
$replace[':'.$oldKey] = array();
foreach($input as $i => $value) {
$replace[':'.$oldKey][] = ':'.$oldKey.$i;
$newArgs[$oldKey.$i] = $value;
}
$replace[':'.$oldKey] = implode(', ', $replace[':'.$oldKey]);
}
$sql = strtr($sql, $replace);
$query = Yii::app()->db->createCommand($sql);
$query->params = $newArgs;
$query->queryAll();
在这个例子中,最终的 sql 和参数是:
SELECT * FROM obj WHERE id IN (:id_array0, :id_array1, :id_array2, :id_array3, :id_array4) AND other_field = :other_value
array(
'id_array0' => 1,
'id_array1' => 2,
'id_array2' => 3,
'id_array3' => 4,
'id_array4' => 5,
'other_value' => 12,
)
在使用原始 SQL 是首选标准的项目中,最大的好处是您可以将其捆绑为实用函数并将其重用于任何查询。遗憾的是 Yii 不会以这种方式自动扩展数组参数,但您也可以自己将这种支持添加到直接使用 PDO 的项目中。
Yii有两种方法:
bindValue()
用于提到的问题bindValues($paramsArray)
要求即$paramsArray = array(':index'=>$value)
我正在使用以下非常适合我的代码:
$query = "UPDATE viewing_request SET ViewingApiResponse=:ViewingApiResponse ,ViewingApiData = :ViewingApiData WHERE id='{$id}'";
$executArray = array(
':ViewingApiResponse'=>$data['ViewingApiResponse'],
':ViewingApiData'=>$data['ViewingApiData']
);
$result = Yii::$app->db->createCommand($query)
->bindValues($executArray)
->execute();