配列をIN()条件にバインドできますか?


562

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();
?>

確かに仕事はどれですか、私が欠けている組み込みのソリューションがあるかどうか疑問に思っていますか?


3
配列をIN()条件にバインドするための完全なガイド(クエリに他のプレースホルダーがある場合を含む
常識

質問はこの質問の複製として締め切られました。この質問は4年前で、ビューが4倍、回答数が3倍、スコアが12倍なので、重複フラグを逆にしました。それは明らかに優れた目標です。
miken32

2020年にこれを見る人は誰でも:github.com/morris/dopを試すことができます。
morris4

回答:


262

私はソウルマージが正しいと思います。クエリ文字列を作成する必要があります。

<?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(コメント)とsomebodyisintroubleの両方がforeachループ...

(...)
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
    $stmt->bindValue(($k+1), $id);

$stmt->execute();

...冗長になる可能性があるため、foreachループと$stmt->executeを単に...に置き換えることができます。

<?php 
  (...)
  $stmt->execute($ids);
?>

(もう一度、私はテストしませんでした)


7
これは興味深い解決策です。IDを繰り返し処理してPDO :: quote()を呼び出すよりも、私は「?」のインデックスを考えています。プレースホルダーは、他のプレースホルダーがクエリの他の場所で最初に発生した場合、混乱するでしょう?
Andru、2009年

5
はい、それは問題になります。ただし、この場合、?ではなく名前付きパラメーターを作成できます。
ステフ2009年

9
古い質問ですが、私が信じる価値があるのは、$foreachbindValue()は必須ではないということです-配列で実行するだけです。例:$stmt->execute($ids);
クリス

2
プレースホルダーの生成は次のように行う必要がありますstr_repeat('?,', count($array) - 1). '?';
Xeoncross

8
これらの知らない人のためのヒント、名前付きパラメータと名前なしパラメータを混在させることはできません。したがって、クエリで名前付きパラメーターを使用する場合は、それらを?に切り替えてから、bindValueインデックスオフセットを増やして、IN?の位置を他の?パラメータ。
justinl 2014年

169

簡単なこと:

//$db = new PDO(...);
//$ids = array(...);

$qMarks = str_repeat('?,', count($ids) - 1) . '?';
$sth = $db->prepare("SELECT * FROM myTable WHERE id IN ($qMarks)");
$sth->execute($ids);

7
私はinput_parameters引数をこのように使用することを考えていませんでした。クエリのパラメーターがINリストよりも多い場合は、array_unshiftとarray_pushを使用して、必要な引数を配列の前後に追加できます。また、私は好む $input_list = substr(str_repeat(',?', count($ids)), 1);
オルカ

7
あなたも試すことができstr_repeat('?,', count($ids) - 1) . '?'ます。関数呼び出しが1つ少なくなります。
オルカ

5
@erfling、これは準備されたステートメントです。注射はどこから行われるのですか?実際の証拠でそれを裏付けることができれば、私は訂正を加えて満足します。
DonVaughn、2015年

5
@erfling、はい、それは正しいです。paramsのバインドはexecute、IDの配列を送信することにより、この例で実行している
とおりです

5
確かに。どういうわけか、配列を渡していたという事実を逃しました。これは確かに安全で良い答えのようです。謝罪いたします。
2015

46

INステートメントを使用することはそれほど重要ですか?FIND_IN_SETop を使用してみてください。

たとえば、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:この回答に対するコメントで指摘した人がいるように、明示的に述べるべきいくつかの問題があります。

  1. FIND_IN_SETテーブルでインデックスを使用せず、まだ実装されていません。MYSQLバグトラッカーでこのレコードを参照してください。通知してくれた@BillKarwinに感謝します。
  2. 検索用の配列の値として、内部にコンマを含む文字列を使用することはできません。implode区切り文字としてコンマ記号を使用しているため、このような文字列を正しい方法で解析することは不可能です。注意してくれた@VaLに感謝します。

結局のところ、インデックスに大きく依存しておらず、検索にコンマを含む文字列を使用しない場合、私の解決策は上記の解決策よりもはるかに簡単、簡単、高速になります。


25
IN()はインデックスを使用でき、範囲スキャンとしてカウントされます。FIND_IN_SET()はインデックスを使用できません。
Bill Karwin 2013年

1
それがポイントです。私はこれを知りませんでした。しかし、いずれにしても、問題のパフォーマンスに関する要件はありません。それほど大きくないテーブルの場合は、プレースホルダーの数が異なるクエリを生成するための個別のクラスよりもはるかに優れており、クリーンです。
Tim Tonkonogov 2013年

11
はい、しかし、最近それほど大きくないテーブルを持っているのは誰ですか?;-)
Bill Karwin 2013年

3
このアプローチのもう1つの問題は、内部にコンマを含む文字列がある場合はどうなるのでしょうか。たとえば、... FIND_IN_SET(description,'simple,search')動作FIND_IN_SET(description,'first value,text, with coma inside')しますが失敗します。そのため、関数は"first value", "text", "with coma inside" 希望の代わりに検索し ます"first value", "text, with coma inside"
VaL 2015

33

多くの動的クエリを実行するため、これは私が作成した非常にシンプルなヘルパー関数です。

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クエリを実行するときに必要になるバインディングも更新します。かんたん!


6
これは、パラメータルールのバインドを壊さないため、はるかに優れたソリューションです。これは、他の人が提案しているインラインSQLを使用するよりもはるかに安全です。
Dimitar Darazhanski

1
素晴らしい。エレガント。完璧です。
リカルシン2017

17

EvilRygyの解決策がうまくいきませんでした。Postgresでは、別の回避策を実行できます。


$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id = ANY (string_to_array(:an_array, ','))'
);
$stmt->bindParam(':an_array', implode(',', $ids));
$stmt->execute();

これは機能しません:ERROR: operator does not exist: integer = text。少なくとも、明示的なキャストを追加する必要があります。
collimarco 2013

17

postgresの非常にクリーンな方法は、postgres-array( "{}")を使用することです:

$ids = array(1,4,7,9,45);
$param = "{".implode(', ',$ids)."}";
$cmd = $db->prepare("SELECT * FROM table WHERE id = ANY (?)");
$result = $cmd->execute(array($param));

SQLインジェクションをブロックしますか?
ファビオ・Zangirolami

1
@FábioZangirolamiそれはPDOなので、そうです。
ESCOBAR 2018

はい、PDO!4年後。あなたの返事は私にとっては問題なく、とてもシンプルで効果的でした。ありがとうございました!!!
ファビオ・Zangirolami

14

これが私の解決策です:

$total_items = count($array_of_items);
$question_marks = array_fill(0, $total_items, '?');
$sql = 'SELECT * FROM foo WHERE bar IN (' . implode(',', $question_marks ). ')';

$stmt = $dbh->prepare($sql);
$stmt->execute(array_values($array_of_items));

array_valuesの使用に注意してください。これにより、主要な順序の問題を修正できます。

IDの配列をマージしてから、重複するアイテムを削除していました。私は次のようなものを持っていました:

$ids = array(0 => 23, 1 => 47, 3 => 17);

そしてそれは失敗していた。


これは優れたソリューションでした。クエリ文字列の作成とは異なり、これはバインディングを正しく使用します。私はこれを強くお勧めします。
Lindylead

注:ソリューションを使用して、配列の前面または背面にアイテムを追加できるため、他のバインディングを含めることができます。 $original_array 元の配列の前に項目を追加:元の配列の array_unshift($original_array, new_unrelated_item); 後に項目を追加: array_push($original_array, new_unrelated_item); 値がバインドされると、new_unrelated項目が正しい場所に配置されます。これにより、配列項目と非配列項目を混在させることができます。`
リンディリード

12

私はPDOを拡張してstefsの提案と同様のことを実行しましたが、長期的には私にとっては簡単でした。

class Array_Capable_PDO extends PDO {
    /**
     * Both prepare a statement and bind array values to it
     * @param string $statement mysql query with colon-prefixed tokens
     * @param array $arrays associatve array with string tokens as keys and integer-indexed data arrays as values 
     * @param array $driver_options see php documention
     * @return PDOStatement with given array values already bound 
     */
    public function prepare_with_arrays($statement, array $arrays, $driver_options = array()) {

        $replace_strings = array();
        $x = 0;
        foreach($arrays as $token => $data) {
            // just for testing...
            //// tokens should be legit
            //assert('is_string($token)');
            //assert('$token !== ""');
            //// a given token shouldn't appear more than once in the query
            //assert('substr_count($statement, $token) === 1');
            //// there should be an array of values for each token
            //assert('is_array($data)');
            //// empty data arrays aren't okay, they're a SQL syntax error
            //assert('count($data) > 0');

            // replace array tokens with a list of value tokens
            $replace_string_pieces = array();
            foreach($data as $y => $value) {
                //// the data arrays have to be integer-indexed
                //assert('is_int($y)');
                $replace_string_pieces[] = ":{$x}_{$y}";
            }
            $replace_strings[] = '('.implode(', ', $replace_string_pieces).')';
            $x++;
        }
        $statement = str_replace(array_keys($arrays), $replace_strings, $statement);
        $prepared_statement = $this->prepare($statement, $driver_options);

        // bind values to the value tokens
        $x = 0;
        foreach($arrays as $token => $data) {
            foreach($data as $y => $value) {
                $prepared_statement->bindValue(":{$x}_{$y}", $value);
            }
            $x++;
        }

        return $prepared_statement;
    }
}

次のように使用できます。

$db_link = new Array_Capable_PDO($dsn, $username, $password);

$query = '
    SELECT     *
    FROM       test
    WHERE      field1 IN :array1
     OR        field2 IN :array2
     OR        field3 = :value
';

$pdo_query = $db_link->prepare_with_arrays(
    $query,
    array(
        ':array1' => array(1,2,3),
        ':array2' => array(7,8,9)
    )
);

$pdo_query->bindValue(':value', '10');

$pdo_query->execute();

1
Markのコメントの最初の部分を取り上げましたが、彼が指摘したよう:arrayに、のようなトークンがクエリ内の文字列にある場合は、まだ安全ではありません。
クリス

4
将来のすべての読者へのメモ:このソリューションは決して使用すべきではありません。アサートは本番コード用ではありません
常識

1
YCS:フィードバックに感謝します。アサートの適合性以外のアプローチについてのあなたの意見に興味があります。
Chris

1
考え方はほぼ同じですが、アサートがなく、より簡単で明示的な方法です。単一のケースの例外ではなく、すべてのクエリを構築する一般的な方法です。すべてのプレースホルダーはそのタイプでマークされています。推測if (is_array($data))作業(のような)は不要になりますが、データ処理方法はより正確になります。
常識

1
コメントを読んでいる人へ:@Your Common Senseで言及された問題はリビジョン4修正されました。
user2428118 14

11

PDO:Predefined Constantsを見ると 、PDOStatement-> bindParamにリストされているように、必要なPDO :: PARAM_ARRAYはありません。

bool PDOStatement :: bindParam(mixed $ parameter、mixed&$ variable [、int $ data_type [、int $ length [、mixed $ driver_options]]])

だからそれは達成できないと思います。


1
うまくいくかわかりません。内破された文字列が引用されると思います。
soulmerge 2009年

2
正解です。引用符がエスケープされるため、機能しません。そのコードを削除しました。

11

他のパラメータがある場合、次のようにすることができます:

$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$query = 'SELECT *
            FROM table
           WHERE X = :x
             AND id IN(';
$comma = '';
for($i=0; $i<count($ids); $i++){
  $query .= $comma.':p'.$i;       // :p0, :p1, ...
  $comma = ',';
}
$query .= ')';

$stmt = $db->prepare($query);
$stmt->bindValue(':x', 123);  // some value
for($i=0; $i<count($ids); $i++){
  $stmt->bindValue(':p'.$i, $ids[$i]);
}
$stmt->execute();

すばらしい答えをありがとう。これは実際に私のために働いたすべての唯一のものでした。しかし、私は1つの間違いを見ました。変数$ rsは$ stmtである必要があります
Piet

11

私にとってよりセクシーな解決策は、動的連想配列を作成して使用することです

// A dirty array sent by user
$dirtyArray = ['Cecile', 'Gilles', 'Andre', 'Claude'];

// we construct an associative array like this
// [ ':name_0' => 'Cecile', ... , ':name_3' => 'Claude' ]
$params = array_combine(
    array_map(
        // construct param name according to array index
        function ($v) {return ":name_{$v}";},
        // get values of users
        array_keys($dirtyArray)
    ),
    $dirtyArray
);

// construct the query like `.. WHERE name IN ( :name_1, .. , :name_3 )`
$query = "SELECT * FROM user WHERE name IN( " . implode(",", array_keys($params)) . " )";
// here we go
$stmt  = $db->prepare($query);
$stmt->execute($params);

実際のシナリオでは
試さ

9

私はこのスレッドが古いことも知っていますが、廃止予定のmysqlドライバーをPDOドライバーに変換するときに、通常のパラメーターとINの両方を同じパラメーターから動的に構築できる関数を作成する必要があるという固有の問題がありましたパラメータ配列。だから私はすぐにこれを構築しました:

/**
 * mysql::pdo_query('SELECT * FROM TBL_WHOOP WHERE type_of_whoop IN :param AND siz_of_whoop = :size', array(':param' => array(1,2,3), ':size' => 3))
 *
 * @param $query
 * @param $params
 */
function pdo_query($query, $params = array()){

    if(!$query)
        trigger_error('Could not query nothing');

    // Lets get our IN fields first
    $in_fields = array();
    foreach($params as $field => $value){
        if(is_array($value)){
            for($i=0,$size=sizeof($value);$i<$size;$i++)
                $in_array[] = $field.$i;

            $query = str_replace($field, "(".implode(',', $in_array).")", $query); // Lets replace the position in the query string with the full version
            $in_fields[$field] = $value; // Lets add this field to an array for use later
            unset($params[$field]); // Lets unset so we don't bind the param later down the line
        }
    }

    $query_obj = $this->pdo_link->prepare($query);
    $query_obj->setFetchMode(PDO::FETCH_ASSOC);

    // Now lets bind normal params.
    foreach($params as $field => $value) $query_obj->bindValue($field, $value);

    // Now lets bind the IN params
    foreach($in_fields as $field => $value){
        for($i=0,$size=sizeof($value);$i<$size;$i++)
            $query_obj->bindValue($field.$i, $value[$i]); // Both the named param index and this index are based off the array index which has not changed...hopefully
    }

    $query_obj->execute();

    if($query_obj->rowCount() <= 0)
        return null;

    return $query_obj;
}

まだテストされていませんが、ロジックはあるようです。

それが同じ立場の人を助けることを願って、

編集:いくつかのテストの後、私は見つけました:

  • PDOは「。」を好まない 彼らの名前で(あなたが私に尋ねると、それはちょっと愚かです)
  • bindParamは間違った関数で、bindValueは正しい関数です。

コードを作業バージョンに編集しました。


8

シュナッレのコードについて少し編集

<?php
$ids     = array(1, 2, 3, 7, 8, 9);
$inQuery = implode(',', array_fill(0, count($ids)-1, '?'));

$db   = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN(' . $inQuery . ')'
);

foreach ($ids as $k => $id)
    $stmt->bindValue(($k+1), $id);

$stmt->execute();
?>

//implode(',', array_fill(0, count($ids)-1), '?')); 
//'?' this should be inside the array_fill
//$stmt->bindValue(($k+1), $in); 
// instead of $in, it should be $id

1
count($ ids)の後に-1を削除しないと機能しません。そうしないと、プレースホルダーが1つ欠けていました。
Marcel Burkhard

7

どのデータベースを使用していますか?PostgreSQLでは、ANY(配列)を使用するのが好きです。したがって、例を再利用するには:

<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id = ANY (:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>

残念ながら、これはかなりポータブルではありません。

他のデータベースでは、他のデータベースが言及しているように、独自の魔法を構成する必要があります。もちろん、そのロジックをクラス/関数に入れて、プログラム全体で再利用できるようにする必要があります。mysql_queryこのシナリオの件名と例についてのさらなる考えについては、PHP.NETのページのコメントをご覧ください。


4

同じ問題を経験した後、私はより簡単な解決策に行きました(ただし、それよりもエレガントではありません) PDO::PARAM_ARRAYが):

与えられた配列$ids = array(2, 4, 32)

$newparams = array();
foreach ($ids as $n => $val){ $newparams[] = ":id_$n"; }

try {
    $stmt = $conn->prepare("DELETE FROM $table WHERE ($table.id IN (" . implode(", ",$newparams). "))");
    foreach ($ids as $n => $val){
        $stmt->bindParam(":id_$n", intval($val), PDO::PARAM_INT);
    }
    $stmt->execute();

... 等々

したがって、混合値配列を使用している場合、タイプparamを割り当てる前に、値をテストするためのコードがさらに必要になります。

// inside second foreach..

$valuevar = (is_float($val) ? floatval($val) : is_int($val) ? intval($val) :  is_string($val) ? strval($val) : $val );
$stmt->bindParam(":id_$n", $valuevar, (is_int($val) ? PDO::PARAM_INT :  is_string($val) ? PDO::PARAM_STR : NULL ));

しかし、私はこれをテストしていません。


4

私が知っているように、配列をPDOステートメントにバインドする可能性はありません。

しかし、2つの一般的な解決策があります。

  1. 位置プレースホルダー(?、?、?、?)または名前付きプレースホルダー(:id1、:id2、:id3)を使用する

    $ whereIn = implode( '、'、array_fill(0、count($ ids)、 '?'));

  2. 以前に配列を引用

    $ whereIn = array_map(array($ db、 'quote')、$ ids);

どちらのオプションも適切で安全です。2番目の方が短いので、必要に応じてパラメーターをvar_dumpできるので、2番目の方が好きです。プレースホルダーを使用して値をバインドする必要があり、最終的にSQLコードは同じになります。

$sql = "SELECT * FROM table WHERE id IN ($whereIn)";

そして私にとって最後で重要なのは、「バインドされた変数の数がトークンの数と一致しない」というエラーを回避することです。

Doctrineは、受信パラメーターを内部で制御できるという理由だけで、位置プレースホルダーを使用する優れた例です。


4

列に整数のみを含めることができる場合は、プレースホルダーなしでこれを実行し、IDをクエリに直接入力するだけで済みます。配列のすべての値を整数にキャストするだけです。このような:

$listOfIds = implode(',',array_map('intval', $ids));
$stmt = $db->prepare(
    "SELECT *
     FROM table
     WHERE id IN($listOfIds)"
);
$stmt->execute();

これは、SQLインジェクションに対して脆弱であってはなりません。


3

これが私の解決策です。PDOクラスも拡張しました:

class Db extends PDO
{

    /**
     * SELECT ... WHERE fieldName IN (:paramName) workaround
     *
     * @param array  $array
     * @param string $prefix
     *
     * @return string
     */
    public function CreateArrayBindParamNames(array $array, $prefix = 'id_')
    {
        $newparams = [];
        foreach ($array as $n => $val)
        {
            $newparams[] = ":".$prefix.$n;
        }
        return implode(", ", $newparams);
    }

    /**
     * Bind every array element to the proper named parameter
     *
     * @param PDOStatement $stmt
     * @param array        $array
     * @param string       $prefix
     */
    public function BindArrayParam(PDOStatement &$stmt, array $array, $prefix = 'id_')
    {
        foreach($array as $n => $val)
        {
            $val = intval($val);
            $stmt -> bindParam(":".$prefix.$n, $val, PDO::PARAM_INT);
        }
    }
}

上記のコードの使用例は次のとおりです。

$idList = [1, 2, 3, 4];
$stmt = $this -> db -> prepare("
  SELECT
    `Name`
  FROM
    `User`
  WHERE
    (`ID` IN (".$this -> db -> CreateArrayBindParamNames($idList)."))");
$this -> db -> BindArrayParam($stmt, $idList);
$stmt -> execute();
foreach($stmt as $row)
{
    echo $row['Name'];
}

どう考えているか教えてください


これが以下のuser2188977の回答に基づいていることを言及するのを忘れていました。
Lippai Zoltan 2013

getOne()とは何かわかりません。PDOの一部ではないようです。PEARでしか見たことがありません。それは正確に何をしますか?
Lippai Zoltan 2013

@YourCommonSenseは、ユーザー定義関数を回答として投稿できますか?
nullability 2013

BindArrayParamこれを整数に制限しているように見えるので、連想配列でデータ型を渡すことをお勧めします。
Ian Brindley 2013年

2

PDOでそのような配列を使用することはできません。

たとえば、各値のパラメータを使用して文字列を作成する(または?を使用する)必要があります。

:an_array_0, :an_array_1, :an_array_2, :an_array_3, :an_array_4, :an_array_5

次に例を示します。

<?php
$ids = array(1,2,3,7,8,9);
$sqlAnArray = join(
    ', ',
    array_map(
        function($index) {
            return ":an_array_$index";
        },
        array_keys($ids)
    )
);
$db = new PDO(
    'mysql:dbname=mydb;host=localhost',
    'user',
    'passwd'
);
$stmt = $db->prepare(
    'SELECT *
     FROM table
     WHERE id IN('.$sqlAnArray.')'
);
foreach ($ids as $index => $id) {
    $stmt->bindValue("an_array_$index", $id);
}

を使い続けたいbindParam場合は、代わりにこれを行うことができます。

foreach ($ids as $index => $id) {
    $stmt->bindParam("an_array_$index", $ids[$id]);
}

?プレースホルダーを使用したい場合は、次のようにします。

<?php
$ids = array(1,2,3,7,8,9);
$sqlAnArray = '?' . str_repeat(', ?', count($ids)-1);
$db = new PDO(
    'mysql:dbname=dbname;host=localhost',
    'user',
    'passwd'
);
$stmt = $db->prepare(
    'SELECT *
     FROM phone_number_lookup
     WHERE country_code IN('.$sqlAnArray.')'
);
$stmt->execute($ids);

$ids空かどうかがわからない場合は、テストしてそれに応じて処理する必要があります(空の配列を返すか、Nullオブジェクトを返すか、例外をスローします...)。


0

プレースホルダーを使用してパラメーターをバインドするという元の質問により近い答えを得るために、もう少し時間をかけました。

この答えは、クエリで使用される配列を介して2つのループを作成する必要があります。しかし、より選択的なクエリのために他の列プレースホルダーを使用するという問題は解決します。

//builds placeholders to insert in IN()
foreach($array as $key=>$value) {
    $in_query = $in_query . ' :val_' . $key . ', ';
}

//gets rid of trailing comma and space
$in_query = substr($in_query, 0, -2);

$stmt = $db->prepare(
    "SELECT *
     WHERE id IN($in_query)";

//pind params for your placeholders.
foreach ($array as $key=>$value) {
    $stmt->bindParam(":val_" . $key, $array[$key])
}

$stmt->execute();

0

最初に「?」の数を設定します クエリで、次に「for」送信パラメータによって、次のようになります。

require 'dbConnect.php';
$db=new dbConnect();
$array=[];
array_push($array,'value1');
array_push($array,'value2');
$query="SELECT * FROM sites WHERE kind IN (";

foreach ($array as $field){
    $query.="?,";
}
$query=substr($query,0,strlen($query)-1);
$query.=")";
$tbl=$db->connection->prepare($query);
for($i=1;$i<=count($array);$i++)
    $tbl->bindParam($i,$array[$i-1],PDO::PARAM_STR);
$tbl->execute();
$row=$tbl->fetchAll(PDO::FETCH_OBJ);
var_dump($row);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.