2012-03-02 9 views
8

は、私は、PHPの場合の下にいる:YIIフレームワークで配列パラメータをバインドする方法は?

$inputs = "1,2,3,4,5"; 
$sql = "SELECT * FROM obj WHERE id IN(:input)"; 

私はYiiのは、DB機能を提供使用:で、正しい

$commond = Yii::app()->db->createCommand($sql); 
$commond->bindValue(":input", $inputs , PDO::PARAM_STR); 

が、クエリの結果を、これはどのようにして行うことができますか?今、この

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

のようにそれを使用するために

+2

Uday Sawantの答えは良い回避策です。上記のコードは、実際にはこのSQL文になります: 'SELECT * FROM obj WHERE id IN( '1,2,3,4,5')'。 '$ inputs'の値は**単一文字列**です。それが結果を間違ってしまう原因です。あなたが本当に 'bindValue'を使わなければならない場合は、[this here](http://stackoverflow.com/questions/6071619/pdo-bind-unknown-number-of-parameters)のような配列からSQLをビルドする必要があります。 – Shiki

答えて

7

私は戻って$command->bindValue()方法で取得しようとするでしょう。

+0

ありがとうございます! – Cherry

1

Uiiのメソッドを使用して、CDbCommandで(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と引数以下のとおりです。生の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, 
) 

は、好ましい標準で、最大の利点は、あなたはユーティリティ関数としてこれをバンドルし、任意のクエリのためにそれを再利用することができます。残念ながら、Yiiはこのように配列引数を自動的には拡張しませんが、PDOを直接使用するプロジェクトにこのサポートを追加することもできます。

6

私のプロジェクトでこの問題が数回発生したので、私はCDbCriteriaを使って次のYiiの回避策を試してみましたが、これはちょっとハッキリですが、paramカウントマッチングのセキュリティを提供します。あなたの例に適用する場合

私のコードは次のようになります。

$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); 

UPDATE

これはYiiのに組み込まれないための非常にクリーンな方法は、実際にあります:

$results = Yii::app()->db->createCommand() 
    ->select() 
    ->from('obj') 
    ->where(['in', 'id', $inputs]) 
    ->queryAll(); 

参照してください。 Docs

関連する問題