95

PDOをIN使用して、値に配列を使用する句を含むステートメントを実行しています。

$in_array = array(1, 2, 3);
$in_values = implode(',', $in_array);
$my_result = $wbdb->prepare("SELECT * FROM my_table WHERE my_value IN (".$in_values.")");
$my_result->execute();
$my_results = $my_result->fetchAll();

上記のコードは完全に正常に機能しますが、私の質問は、なぜこれが機能しないのかということです。
 $in_array = array(1, 2, 3);
    $in_values = implode(',', $in_array);
    $my_result = $wbdb->prepare("SELECT * FROM my_table WHERE my_value IN (:in_values)");
    $my_result->execute(array(':in_values' => $in_values));
    $my_results = $my_result->fetchAll();

このコードはmy_value、(1)の最初のアイテムに等しいアイテムを返します$in_arrayが、配列(2、および3)の残りのアイテムは返しません。

4

9 に答える 9

138

PDOはそのようなことには不向きです。通常の方法で配列値をバインドしながら、プレースホルダーを使用して動的に文字列を作成し、クエリに挿入する必要があります。位置プレースホルダーを使用すると、次のようになります。

$in  = str_repeat('?,', count($in_array) - 1) . '?';
$sql = "SELECT * FROM my_table WHERE my_value IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($in_array);
$data = $stm->fetchAll();

クエリに他のプレースホルダーがある場合は、次のアプローチを使用できます (コードは私のPDO チュートリアルから取得されます)。

関数を使用array_merge()してすべての変数を 1 つの配列に結合し、他の変数をクエリに表示される順序で配列の形式で追加できます。

$arr = [1,2,3];
$in  = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT * FROM table WHERE foo=? AND column IN ($in) AND bar=? AND baz=?";
$stm = $db->prepare($sql);
$params = array_merge([$foo], $arr, [$bar, $baz]);
$stm->execute($params);
$data = $stm->fetchAll();

名前付きプレースホルダーを使用している場合、名前付きプレースホルダーのシーケンスを作成する必要があるため、コードはもう少し複雑になります:id0,:id1,:id2。したがって、コードは次のようになります。

// other parameters that are going into query
$params = ["foo" => "foo", "bar" => "bar"];

$ids = [1,2,3];
$in = "";
$i = 0; // we are using an external counter 
        // because the actual array keys could be dangerous
foreach ($ids as $item)
{
    $key = ":id".$i++;
    $in .= ($in ? "," : "") . $key; // :id0,:id1,:id2
    $in_params[$key] = $item; // collecting values into a key-value array
}

$sql = "SELECT * FROM table WHERE foo=:foo AND id IN ($in) AND bar=:bar";
$stm = $db->prepare($sql);
$stm->execute(array_merge($params,$in_params)); // just merge two arrays
$data = $stm->fetchAll();

幸いなことに、名前付きプレースホルダーについては、厳密な順序に従う必要がないため、配列を任意の順序でマージできます。

于 2013-02-08T07:28:01.003 に答える
18

PDO 準備済みステートメントでの変数置換は、配列をサポートしていません。1対1です。

配列の長さに基づいて必要な数のプレースホルダーを生成することで、この問題を回避できます。

$variables = array ('1', '2', '3');
$placeholders = str_repeat ('?, ',  count ($variables) - 1) . '?';

$query = $pdo -> prepare ("SELECT * FROM table WHERE column IN($placeholders)");
if ($query -> execute ($variables)) {
    // ...
}
于 2013-02-08T07:22:30.587 に答える