PDO IN () Задание массива и местозаполнитель

Я нашел этот код на SO, который отлично подходит для использования PDO и оператора IN ().

$values = explode(',', $values) ; # 1,4,7 $placeholders = rtrim(str_repeat('?, ', count($values)), ', ') ; $query = "SELECT * FROM table WHERE id IN ($placeholders)"; $stm = $db->prepare($query) ; $stm->execute($values) ; 

Однако, как я могу смешивать в другом дополнении к запросу, чтобы запрос выглядел следующим образом:

 $query = "SELECT * FROM table WHERE id IN ($placeholders) AND product=?"; $stm = $db->prepare($query) ; $stm->execute(array($values,$product)) ; //error happens when adding product placeholder 

Я думал, что это сработает, но я получаю:

Предупреждение: PDOStatement :: execute () [pdostatement.execute]: SQLSTATE [HY093]: Недопустимый номер параметра: количество связанных переменных не совпадает с числом токенов в строке 3 (строка $ stm)

Любая идея, как заставить это вести себя так, как предполагалось?

ОБНОВЛЕНО выполнить массив, все еще не работающий.

Решение

Это должно работать, если $values – массив:

 $query = "SELECT * FROM table WHERE id IN ($placeholders) AND product=?"; $stm->execute(array_merge($values, array($product))); 

объяснение

execute() ожидает, что будет предоставлен один параметр – в этом случае массив. Добавляя array_merge($values, array($product)) вы создаете один массив с добавлением $product в конце, поэтому запрос должен работать правильно.

Смотрите демонстрацию здесь: http://ideone.com/RcClX

 $stm->execute($values,$product) ; //error happens when adding product placeholder 

Проблема здесь в том, что execute требует одного массива. Вы не можете передавать несколько массивов, и, что еще хуже, вы не можете встраивать массивы.

У нас уже есть отличный класс $values , поэтому давайте его повторно использовать после создания строки-заполнителя.

 $values = explode(',', $values) ; # 1,4,7 $placeholders = rtrim(str_repeat('?, ', count($values)), ', ') ; $query = "SELECT * FROM table WHERE id IN ($placeholders) AND product=?"; // New! $values[] = $product; $stm = $db->prepare($query); $stm->execute($values); 

И другое решение может быть (если вам нравится: param_name = $ value way, как я):

 $params = array( ':product' => $product ); $_in_params = array(); foreach ( $_in_values as $idx_in => $value_in) { $_in_params[] = ':param_in_'.$idx_in; $params[':param_in_'.$idx_in] = $value_in; } $query .= "SELECT * FROM table WHERE id IN (".join(',',$_in_params).") AND product=:product"; 

Я не уверен, что это лучшее и оптимальное решение, но оно немного читаемо для человека 🙂 И это может быть полезно, если у вас большой сложный запрос, и вы хотите его отладить

(Мне любопытно, есть ли у кого-то хороший аргумент, почему НЕ делать так)

Вы забыли подготовить его ^ _ ^

 $query = "SELECT * FROM table WHERE id IN ($placeholders) AND product=?"; $stm = $db->prepare($query) ; $stm->execute($values,$product) ; //p00f 

И помимо этого execute() должен иметь только один параметр

Так что выше не будет работать ВСЕ !

См. DOC

Версия для заметок, если вам это нужно

 $values = [1, 4, 7, 8]; $placeholders = preg_filter('/^/', ':prefix_', array_keys($values))); $query = 'SELECT * FROM table WHERE id IN ( '. implode(', ', $placeholders) . ')'; $stmt = $db->prepare($query); if (count($values) > 0) { foreach ($values as $key => $current_value) { $stmt->bindValue($placeholders[$key] , $current_value, PDO::PARAM_STR); } } $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC);