PHP - Using PDO with IN clause array

前端 未结 8 1689
失恋的感觉
失恋的感觉 2020-11-21 06:03

I\'m using PDO to execute a statement with an IN clause that uses an array for its values:

$in_array = array(1, 2, 3);
$in_values = implode(\',\'         


        
相关标签:
8条回答
  • 2020-11-21 07:03

    I've just come up against this problem and coded a small wrapper. It's not the prettiest or best code I'm sure, but it might help somebody so here it is:

    function runQuery(PDO $PDO, string $sql, array $params = [])
    {
        if (!count($params)) {
            return $PDO->query($sql);
        }
    
        foreach ($params as $key => $values) {
            if (is_array($values)) {
                // get placeholder from array, e.g. ids => [7,12,3] would be ':ids'
                $oldPlaceholder  = ':'.$key;
                $newPlaceholders = '';
                $newParams = [];
                // loop through array to create new placeholders & new named parameters
                for($i = 1; $i <= count($values); $i++) {
                    // this gives us :ids1, :ids2, :ids3 etc
                    $newKey = $oldPlaceholder.$i;
                    $newPlaceholders .= $newKey.', ';
                    // this builds an associative array of the new named parameters
                    $newParams[$newKey] = $values[$i - 1];
                }
                //trim off the trailing comma and space
                $newPlaceholders = rtrim($newPlaceholders, ', ');
    
                // remove the old parameter
                unset($params[$key]);
    
                // and replace with the new ones
                $params = array_merge($params, $newParams);
    
                // amend the query
                $sql = str_replace($oldPlaceholder, $newPlaceholders, $sql);
            }
        }
    
        $statement = $PDO->prepare($sql);
        $statement->execute($params);
        return $statement;
    }
    

    E.g, passing these in:

    SELECT * FROM users WHERE userId IN (:ids)
    
    array(1) {
      ["ids"]=>
      array(3) {
        [0]=>
        int(1)
        [1]=>
        int(2)
        [2]=>
        int(3)
      }
    }
    

    Becomes:

    SELECT * FROM users WHERE userId IN (:ids1, :ids2, :ids3)
    
    array(3) {
      [":ids1"]=>
      int(1)
      [":ids2"]=>
      int(2)
      [":ids3"]=>
      int(3)
    }
    

    It's not bulletproof, but as a sole dev for my needs it does the job fine, so far anyway.

    0 讨论(0)
  • 2020-11-21 07:05

    As I understand it it is because PDO will treat the $in_values contents as a single item and will quite it accordingly. PDO will see 1,2,3 as a single string so the query will look something like

    SELECT * FROM table WHERE my_value IN ("1,2,3")

    You may think that changing the implode to have quotes and commas will fix it, but it will not. PDO will see the quotes and change how it quotes the string.

    As to why your query matches the first value, I have no explanation.

    0 讨论(0)
提交回复
热议问题