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 линия)
Любая идея, как заставить это вести себя так, как предполагалось?
ОБНОВЛЕНО выполнить массив, все еще не работающий.
Ответы
Ответ 1
Решение
Это должно работать, если $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
Ответ 2
$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);
Ответ 3
И другое решение может быть (если вам нравится: 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";
Я не уверен, что это лучшее и оптимальное решение, но оно немного читаемо для человека:) И это может быть полезно, если у вас большой сложный запрос, и вы хотите его отладить
(Мне любопытно, есть ли у кого-то хороший аргумент, почему НЕ делать так)
Ответ 4
Ты забыл подготовить его ^ _ ^
$query = "SELECT * FROM table WHERE id IN ($placeholders) AND product=?";
$stm = $db->prepare($query) ;
$stm->execute($values,$product) ; //p00f
И кроме этого execute()
должен иметь только один параметр
Таким образом, выше не будет работать ВСЕ!
См. DOC
Ответ 5
Версия держателей, если вам это нужно
$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);