Php 我可以将数组绑定到IN()条件吗?

Php 我可以将数组绑定到IN()条件吗?,php,arrays,pdo,prepared-statement,where-in,Php,Arrays,Pdo,Prepared Statement,Where In,我很想知道是否可以使用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-&g

我很想知道是否可以使用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();
?>
$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();
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
$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();
<?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);
让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();
?>
这当然可以,但我只是想知道是否有一个内置的解决方案我错过了?

看看有没有PDO::PARAM_数组,您将需要它,如上所列

bool PDOStatement::bindParam mixed$参数,mixed&$变量[,int$数据类型[,int$长度[,mixed$驱动程序选项]]


所以我认为这是不可能实现的

您必须构造查询字符串

<?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();
?>
。。。可能是多余的,所以foreach循环和$stmt->execute可以被替换为

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

你在使用什么数据库?在PostgreSQL中,我喜欢使用ANYarray。因此,要重用您的示例:

<?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();
?>
不幸的是,这是非常不可移植的


在其他数据库上,您需要像其他人所提到的那样创造自己的魔力。当然,您需要将该逻辑放入类/函数中,以使其在整个程序中可重用。查看PHP.NET上mysql_查询页面上的评论,了解有关此场景主题和示例的更多想法。

关于Schnalle代码的一些编辑

<?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

邪恶的解决方案对我不起作用。在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();

我扩展了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;
    }
}
您可以这样使用它:

<?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();
?>
$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();
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
$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();
<?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);
要快速了解:

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

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

我也意识到这个线程很旧,但我遇到了一个独特的问题,在将即将弃用的mysql驱动程序转换为PDO驱动程序时,我必须创建一个函数,该函数可以动态地从同一个参数数组构建普通参数和INs。所以我很快建立了这个:

/**
 * 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是正确的函数。
代码被编辑为工作版本。

在经历了同样的问题之后,我选择了一个更简单的解决方案,尽管仍然没有PDO::PARAM_数组那么优雅:

给定数组$ids=array2,4,32:

。。。等等

因此,如果您使用的是混合值数组,则在分配类型参数之前,需要更多代码来测试您的值:

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

但是我还没有测试过这个。这是我的解决方案。我还扩展了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'];
}
让我知道你的想法

在声明中使用它很重要吗?尝试使用FIND_IN_SET op

例如,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:正如一些人在对这个答案的评论中指出的那样,有一些问题需要明确说明

FIND_IN_SET不在表中使用索引,它还没有实现-请参阅。感谢@BillKarwin的通知。 不能使用内部带有逗号的字符串作为搜索数组的值。由于使用逗号符号作为分隔符,所以在内爆后不可能以正确的方式解析此类字符串。感谢@VaL的提示。
总之,如果您不严重依赖索引,也不使用带逗号的字符串进行搜索,那么我的解决方案将比上面列出的解决方案更简单、更简单、更快。

因为我做了很多动态查询,这是我制作的一个超级简单的助手函数

public static function bindParamArray($prefix, $values, &$bindArray)
{
    $str = "";
    foreach($values as $index => $value){
        $str .= ":".$prefix.$index.",";
        $bindArray[$prefix.$index] = $value;
    }
    return rtrim($str,",");     
}
像这样使用它:

<?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();
?>
$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();
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
$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();
<?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);

返回字符串:id1、:id2、:id3,并更新运行查询时所需的$bindArray绑定。轻松点

postgres非常干净的方法是使用postgres数组{}:

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

据我所知,不可能将数组绑定到PDO语句中

但存在两种常见的解决方案:

使用位置占位符?,?,?,?或命名占位符:id1,:id2,:id3

$where=内爆“,”,数组_fill0,计数$id“?”

引用前面的数组

$where=array_maparray$db,'quote',$id

这两种选择都是好的和安全的。 我更喜欢第二个,因为它比较短,如果需要,我可以使用var_转储参数。 使用占位符,您必须绑定值,最终您的SQL代码将是相同的

$sql = "SELECT * FROM table WHERE id IN ($whereIn)";
最后也是对我来说很重要的一点是避免错误绑定变量的数量与令牌的数量不匹配


这是使用位置占位符的一个很好的例子,只是因为它对传入的参数有内部控制。

我进一步了解了使用占位符绑定参数的原始问题

这个是 wer必须在查询中使用的数组中进行两次循环。但它确实解决了为更具选择性的查询使用其他列占位符的问题

//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();
以下是我的解决方案:

$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));
注意数组_值的使用。这可以解决密钥排序问题

我正在合并ID数组,然后删除重复项。我有点像:

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

这是失败的。

当您有其他参数时,您可以这样做:

<?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();
?>
$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();
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
$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();
<?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);

如果列只能包含整数,则可能不使用占位符,直接将ID放入查询中。您只需将数组的所有值强制转换为整数。像这样:

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

这应该不会受到任何SQL注入的攻击。

您首先设置了多少?在查询中,然后通过发送参数 像这样:

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

对我来说,更性感的解决方案是构造一个动态关联数组并使用它

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

在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);
}
如果你想用?占位符,您可以这样做:

<?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();
?>
$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();
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
$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();
<?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是否为空,您应该测试它并相应地处理该情况返回空数组,或返回空对象,或引发异常,…。

对于MySQL和PDO,我们可以使用JSON数组和JSON_包含来搜索

$ids = [123, 234, 345, 456]; // Array of users I search
$ids = json_encode($ids); // JSON conversion

$sql = <<<SQL
    SELECT ALL user_id, user_login
    FROM users
    -- Cast is mandatory beaucause JSON_CONTAINS() waits JSON doc candidate
    WHERE JSON_CONTAINS(:ids, CAST(user_id AS JSON))
    SQL;

$search = $pdo->prepare($sql);
$search->execute([':ids' => $ids]);
$users = $search->fetchAll();


我不知道这是否有效。我猜内爆的字符串会被引用。你是对的,引号会被转义,这样就赢了;不行。我已经删除了这段代码。这是一个有趣的解决方案,虽然我更喜欢在ID上迭代并调用PDO::quote,但我认为如果在查询的其他地方首先出现任何其他占位符,则“?”占位符的索引将变得混乱,对吗?是的,这将是一个问题。但在本例中,您可以创建命名参数,而不是?s。旧问题,但我认为值得注意的是,$foreach和bindValue不是必需的,只需使用数组执行即可。例如:$stmt->execute$id;生成占位符应该像str_repeat'?,'count$array-1'?'这样完成;这只是给那些不知道的人的提示,您不能混合使用命名参数和未命名参数。因此,如果您在查询中使用命名参数,请将它们切换到?s,然后增加bindValue索引偏移量,以使in?的位置与它们相对于其他参数的位置相匹配?太好了,我没有想过用这种方式使用input_parameters参数。对于那些查询的参数比IN列表中的参数多的查询,可以使用array_unshift和array_push将必要的参数添加到数组的前端和末尾。另外,我更喜欢$input_list=substrstrstr_repeat',?',count$id,1;您也可以尝试str_repeat“?,”,count$id-1。“?”。少一个函数调用。@erfling,这是一个准备好的语句,注入从哪里来?如果您能用一些实际的证据来证明这一点,我将非常乐意进行任何更正。@erfling,是的,这是正确的,绑定参数正是我们在本例中通过发送一个idsOh数组执行的操作。不知怎的错过了你通过阵列的事实。这确实看起来是安全的,也是一个很好的答案。我很抱歉。我已经回答了Mark评论的第一部分,但正如他所指出的,如果查询中的字符串中包含:array这样的标记,这仍然是不安全的。请所有未来读者注意:永远不要使用此解决方案。资产不适用于生产代码:感谢您的反馈,您对资产适用性之外的方法的意见很感兴趣。想法基本相同,但没有资产,更直接、更明确的方式-不是作为单个案例的例外,而是作为构建每个查询的一般方式。每个占位符都标记有其类型。这使得猜测变得不必要,比如if_array$data,但使数据处理方式更加准确。对于阅读评论的任何人来说:@Your Common Sense提到的问题已经解决。忘了提到这是基于下面user2188977的答案。我不确定getOne是什么,它似乎不是PDO的一部分。我只在梨上见过。它到底是做什么的?@YourCommonSense您可以发布您的用户定义函数作为答案吗?我建议将数据类型传递给关联数组中的BindArrayParam,因为您似乎将其限制为整数。in可以使用索引,并作为范围扫描计数。在集合中查找不能使用索引。这是一个要点。我不知道这件事。但无论如何,在这个问题上对性能没有任何要求。对于不太大的表,它比单独的类生成具有不同占位符数的查询要好得多,也更干净-这种方法的另一个问题是,如果有带逗号的字符串呢
在…内例如在_SETdescription中查找_,'simple,search'将起作用,但在_SETdescription中查找_,'first value,text,with coma inside'将失败。因此,函数将搜索包含coma的第一个值text,而不是所需的包含coma的第一个值text。此操作不起作用:错误:运算符不存在:整数=文本。至少您需要添加显式转换。这是一个更好的解决方案,因为它不会破坏参数绑定规则。这比这里其他人提出的使用内联sql要安全得多。谢谢你的回答。这是唯一一个真正对我有用的。然而,我发现了一个错误。变量$rs应该是$stmtI必须在count$id之后删除-1才能为我工作,否则将始终缺少一个占位符。包括在queryQuestion中有其他占位符的情况作为的副本关闭。我颠倒了重复标志,因为这个问题比我大4岁,有4倍的观点,3倍的答案,12倍的分数。这显然是一个更高的目标。任何人在2020年看到这一点:你可以尝试一下。它阻止sql注入?@FábioZangirolami它是PDO,所以是的。是的,PDO!4年后。你的回答对我来说很好,非常简单有效。非常感谢。如果不在真实场景中尝试,很难确定,但似乎很好。+1这是一个极好的解决方案。与构建查询字符串不同,它正确地使用绑定。我强烈推荐这一个。注意:使用您的解决方案,您可以将项添加到数组的前面或后面,以便可以包含其他绑定$原始数组在原始数组之前添加项:数组\u取消移位$original\u数组,新的\u无关\u项;在原始数组后添加项目:数组\推送$original\数组,新建\无关\项目;绑定值时,新的\u无关项将被放置在正确的位置。这允许您混合使用数组项和非数组项`