【问题标题】:How to bind array parameters in Yii framework?Yii框架中如何绑定数组参数?
【发布时间】:2012-03-02 07:12:49
【问题描述】:

我有以下代码:

$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 条件绑定参数?

【问题讨论】:

  • Uday Sawant 的回答是一个很好的解决方法。您上面的代码实际上会产生这个 SQL 语句:SELECT * FROM obj WHERE id IN ('1,2,3,4,5')。请注意,$inputs 的值是一个单个字符串。这就是导致结果不正确的原因。如果您真的必须使用bindValue,则必须从this here 等数组构建SQL。

标签: php yii yii1.x


【解决方案1】:

暂时这样使用

$command = Yii::app()->db->createCommand()
    ->select()
    ->from('tableName')
    ->where(array('in', 'id', explode(',', $inputs)));

我会尝试使用$command->bindValue() 方法返回。

【讨论】:

    【解决方案2】:

    在我的项目中多次遇到这个问题后,我想出了以下使用 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();
    

    Docs

    【讨论】:

      【解决方案3】:

      在 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 的项目中。

      【讨论】:

        【解决方案4】:

        Yii 中有两种方法:

        1. bindValue() 用于上述问题
        2. 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();
        

        【讨论】:

        • 这个问题是关于 Yii 1.1 中的 IN 条件,你的回答是关于 Yii 2 并没有真正回答这个问题。
        猜你喜欢
        • 1970-01-01
        • 2011-02-15
        • 1970-01-01
        • 1970-01-01
        • 2019-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-29
        相关资源
        最近更新 更多