Mysql implode в запросе к mysql

Вейдер

Новичок
Добрый день. Помогите в моей проблеме.

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

// Выражение Select
$select = 'SELECT uk.id_uk, uk.code_uk, uk.name_uk, gorod.name_gorod, uk.address_uk, uk.inn_uk, uk.director_uk';
$from = ' FROM uk, gorod';
$where = ' WHERE (uk.id_gorod = gorod.id_gorod)';

$placeholders = array();

// Список выбранных городов в фильтре
if(isset($_POST['gorod']) && is_array($_POST['gorod'])) {
$where .= ' AND (uk.id_gorod IN ( :filter_gorod ))';
$placeholders[':filter_gorod'] = implode(',', $_POST['gorod']);
}

// Если была указана строка для поиска
if ($_POST['WhatFind'] != '') {
$where .= ' AND ((uk.name_uk LIKE :search) OR (uk.code_uk LIKE :search))';
$placeholders[':search'] = '%' . $_POST['WhatFind'] . '%';
}

$sql = $select . $from . $where;
$s = $pdo->prepare($sql);
$s->execute($placeholders);

Так вот, select без поиска и фильтра работает нормально. Поиск тоже. А вот фильтр работает не так как надо: если выбран два и более городов, то выдаются результаты только по первому городу, остальные, почему-то, игнорятся. Например: выбираю 3 города.

print_r($_POST['gorod']) выдает Array ( [1] => 3 [2] => 2 [3] => 1 ) все нормально.

print_r($placeholders) выдает Array ( [:filter_gorod] => 3,2,1 ) вроде тоже все нормально, но выводятся организации только для первого города, в данном случае для id=3. Почему так происходит?

P.S. причем, если подставляю id городов напрямую в выражение $where .= ' AND (uk.id_gorod IN ( 3,2,1 ))'; то все работает как надо, выдаются результаты по всем трем городам
 
Последнее редактирование:

Andkorol

Новичок
Возможно, причина в том, что данные из плейсхолдеров при подстановке в запрос автоматически экранируются кавычками.
В результате, в твоём случае, в запросе вполне может получиться что-то вроде: ... AND (uk.id_gorod IN ( '3,2,1' ))
Т.е. в IN вместо трёх значений попадает одно: '3,2,1'.

P.S.: http://phpfaq.ru/pdo#in
 

Вейдер

Новичок
Если бы в IN вместо трёх значений попадало одно: '3,2,1', то фильтр бы не выдал вообще ничего, он бы искал город с id='3,2,1', но он выдает города с id=3. Тут как я понимаю в IN попадает либо только одно значение 3, либо попадают все, но все они потом отбрасываются, кроме первого. Почему так происходит и как это обойти - не пойму.
 

Andkorol

Новичок
Если бы в IN вместо трёх значений попадало одно: '3,2,1', то фильтр бы не выдал вообще ничего
Если бы ты включил логирование запросов, и посмотрел лог MySQL-запросов – ты бы убедился, что в запрос попадает именно строка: IN ('3,2,1').
Варианты:
– неименованные плейсхолдеры (ссылка выше);
– подставляй параметры для IN прямо в запрос, не забывая о безопасности (intval(), (int)$var и всё такое);
– можно попробовать извратиться как-то типа так;
 

Andkorol

Новичок
Тут как я понимаю в IN попадает либо только одно значение 3, либо попадают все, но все они потом отбрасываются, кроме первого. Почему так происходит ...
В таблице поле `uk.id_gorod` явно имеет тип INT – поэтому происходит автоматическое приведение типа данных в IN к типу данных соответствующего поля.
Если в IN вместо 3-х чисел передаётся одна строка с тремя числами ('3,2,1') – то происходит оно примерно так:
PHP:
$ php -a
Interactive shell

php > $var = '3,2,1';
php > var_dump((int)$var);
int(3)
 

Вейдер

Новичок
Да, Andkorol, ты прав. Спасибо за разъяснение. Даже не знаю какой из предложенных вариантов лучше реализовать
 

Andkorol

Новичок
Я б на твоём месте попробовал реализовать все варианты – для опыта.
А потом уже сам решишь, какой из вариантов проще и удобнее лично для тебя.
 
Сверху