Блог Михаила Крамера. PHP и JS

Динамическое формирование where для создания фильтров

Написать этот пост меня побудили вопросы на эту тему на форуме php.ru. Итак, нужно при задании фильтров каких-то объектов (например, товаров) динамически формировать where. Сейчас я покажу, как это делается в построителях запросов известных мне фреймворкоа. Возьмём простой случай, когда все поля для фильтрации в одной таблице, и не требуется join-ов.

На самом деле, всё это очень просто сделать при помощи чудесной функции implode, предварительно накопив все условия в массиве:

function makeWhere($filters) {
    global $db; // предполагается, что в глобальной переменной $db содержится
                // правильно инициализированный объект mysqli
    $wheres = []; // Замените на array(), если у вас php < 5.4
    foreach ($filters as $key=>$value) {
         // не забываем экранировать спец. символы SQL, а также заключить имя поля в обратные кавычки
         // на случай совпадения последнего с зарезервированным словом SQL
         $wheres[] = sprintf("`%s`='%s'", $key, $db->real_escape_string($value));
    }
    
    return implode(" and ", $wheres);
}

Как видно из комментариев, я предположил, что для работы с БД использовано расширение mysqli, и объект mysqli помещён в глобальную переменную $db. Конечно, глобальные переменные использовать не очень хорошо, но, по моему мнению, одна-две проблемы не представляют.

Используется эта функция так:


$sql = "select * from goods where" . makeWhere(["color"=>"красный", "season" => "Лето"]);
echo $sql; 
/* Вывод:
select * from goods where `color`='красный' and `season`='Лето';
*/

Для использования других операций, таких, как >, < и т.п., необходимо дописать функцию makeWhere(), например так:


function makeWhere($filters) {
    global $db; // предполагается, что в глобальной переменной $db содержится
                // правильно инициализированный объект mysqli
    $wheres = []; // Замените на array(), если у вас php < 5.4
    foreach ($filters as $key=>$value) {
         if (!is_array($value)) {
             // не забываем экранировать спец. символы SQL, а также заключить имя поля в обратные кавычки
             // на случай совпадения последнего с зарезервированным словом SQL
             $wheres[] = sprintf("`%s`='%s'", $key, $db->real_escape_string($value));
         }
         else {
              $wheres[] = sprintf"`%s` %s '%s'", $value[0], $value[1], $db->real_escape_string($value[2]));
         }
    }
    
    return implode(" and ", $wheres);
}

Теперь вы можете использовать это так:

echo makeWhere(['color'=>'красный', ['price', "<", 123]]);

Ваш комментарий
Комментарии