PHP PDO: Как правильно передать массив значений в подготовленный запрос (Prepared Statement) без использования циклов?

При работе с PHP PDO часто возникает задача передать массив значений в подготовленный запрос — например, для оператора `IN (…)`. Наивный подход через цикл работает, но существуют более элегантные решения.

## Стандартный подход без явного цикла

Самый распространённый способ — динамически сформировать строку плейсхолдеров с помощью `implode` и `array_fill`, а затем передать массив через `execute()`:

php
$ids = [1, 2, 3, 4, 5];
$placeholders = implode(‘,’, array_fill(0, count($ids), ‘?’));
$sql = «SELECT * FROM users WHERE id IN ($placeholders)»;
$stmt = $pdo->prepare($sql);
$stmt->execute($ids);
$results = $stmt->fetchAll();

Здесь `array_fill(0, count($ids), ‘?’)` создаёт массив из нужного количества знаков вопроса, а `implode` соединяет их запятыми. Никакого явного цикла — всё делается встроенными функциями PHP.

## Использование именованных плейсхолдеров

Если нужны именованные плейсхолдеры, можно использовать `array_map`:

php
$ids = [1, 2, 3];
$keys = array_map(fn($i) => «:id$i», array_keys($ids));
$placeholders = implode(‘,’, $keys);
$params = array_combine($keys, $ids);

$sql = «SELECT * FROM users WHERE id IN ($placeholders)»;
$stmt = $pdo->prepare($sql);
$stmt->execute($params);

## Важные нюансы

**Типизация данных.** При передаче через `execute()` все значения привязываются как строки (`PDO::PARAM_STR`). Если критична типизация (например, для целых чисел), используйте `bindValue()` в цикле или убедитесь, что СУБД корректно приводит типы.

**Пустой массив.** Обязательно проверяйте массив на пустоту перед формированием запроса — `IN ()` вызовет SQL-ошибку:

php
if (empty($ids)) {
// вернуть пустой результат или выбросить исключение
return [];
}

**Безопасность.** Описанный подход полностью защищён от SQL-инъекций, так как значения передаются через механизм привязки параметров PDO, а не интерполируются в строку запроса напрямую.

## Вспомогательная функция

Для удобства повторного использования можно вынести логику в функцию:

php
function pdoInQuery(PDO $pdo, string $table, string $column, array $values): PDOStatement {
if (empty($values)) {
throw new InvalidArgumentException(‘Массив значений не может быть пустым’);
}
$placeholders = implode(‘,’, array_fill(0, count($values), ‘?’));
$stmt = $pdo->prepare(«SELECT * FROM $table WHERE $column IN ($placeholders)»);
$stmt->execute(array_values($values));
return $stmt;
}

Такой подход чист, безопасен и не требует написания явных циклов в основном коде приложения.


Задайте вопрос нейросети

Не нашли ответ? Спросите ИИ — он подготовит развёрнутую статью.