Фильтрация
При выводе списков данных из моделей фильтрация делается на основании параметров из раздела Конструктор запросов. С его помощью можно делать SQL выборку по нужным параметрам. На frontend части сайта бывает необходимость организовать поиск записей (товаров, новостей, и т.д.) по нескольким параметрам. Для такой задачи используется класс "Filter" и его объект, находящийся внутри объекта модели.
Рассмотрим фильтрацию на примере модели предметов мебели.
class Furniture extends Model { protected $name = "Мебель"; protected $model_elements = array( array("Активен", "bool", "active", array("on_create" => true)), array("Изображения", "multi_images", "images"), array("Описание", "text", "desc"), array("Цена", "int", "price"), array("Площадь комнаты", "int", "square"), array("Расположение", "enum", "location", array("empty_value" => true, "values_list" => array("badroom" => "В спальне", "livingroom" => "Гостиной", "childrenroom" => "В детской", "corridor" => "В коридоре"))) ); }
Нас интересуют поля "price", "square" и "location", по которым мы будем делать фильтрацию товаров. В файле шаблона создадим объект класса "Filter", который может принимать GET параметры со значениями фильтров ("price-from=12000&square-to=50&location=livingroom"). При запуске объекта поиск GET параметров запускается автоматически.
//Запуск объекта фильтра для модели $mv -> furniture -> runFilter(array("price", "square", "location")); //Теперь внутри модели доступен объект фильтрации $mv -> furniture -> filter; //Вывод полей всех запущенных фильтров echo $mv -> furniture -> filter -> display(); //Вывод выборочных фильтров в нужной последовательности echo $mv -> furniture -> filter -> display(array("location", "price")); //Вывод одного фильтра echo $mv -> furniture -> filter -> display("square"); //Форма для запуска фильтров в шаблоне <form method="get" action="<? echo $mv -> root_path; ?>my-page/"> <? echo $mv -> furniture -> filter -> display(); ?> <input type="submit" value="Найти" /> </form>
Методы объекта Filter
- display() - выводит HTML код для полей фильтров или одного поля (примеры выше), переданные значения подставляются автоматически
- displayCheckbox($field) - выводит HTML код для полей типа "bool","image","file","multi_images" в виде элемента "checkbox" (по умолчанию выводится тэг "select" с вариантами "да", "нет", "не задан"). В случае с "checkbox" значение "нет" не определяется, т.е. если он отмечен, то будет идти поиск по ячейкам со значением равным "1", а если не отмечен, то данное поле в поиске не участвует.
- getConditions() - возвращает массив значений переданных фильтров, в формате Конструктор запросов
- getUrlParams() - возвращает список GET параметров значений фильтров для URL
- addUrlParams($path) - добавляет значения (GET параметры) установленных фильтров к переданному URL
- hasParams() - проверяет установлен ли хотя бы один фильтр, если да, то вернет "true"
- getValue($field, [$condition]) - возвращает значение фильтра если оно передано в GET, второй необязательный параметр нужен для полей типа "date","date_time","int","float","order", в которых значения передаются как интервалы. Параметр принимает значения "from" и "to".
- setValue($field, $value, [$condition]) - позволяет вставить значение для фильтра, принимает в качестве аргументов название поля и значение. Необязательный параметр нужен для передачи параметров для интервальных фильтров, аналогично предыдущему методу.
- addFilter($caption, $type, $name, [$extra_params]) - добавляет новый фильтр в объект filter, аргументы аналогичны типам данных
- removeFilter($field) - удаляет фильтр по названию поля
- setCaption($field, $caption) - устанавливает название (подпись) поля в списке фильтров
- setEnumEmptyValueTitle($field, $title) - для полей типа "enum" можно менять подпись пустого значения (используется в случаях когда в самом теге "select" нужно поставить его название), см. пример ниже. Для данного элемента модели изначальна должна быть задана опция "empty_value" => "true".
- displaySingleField($field) - для полей типа "date","date_time","int","float","order" по умолчанию выводятся 2 окна (input) с целью задания интервала значений ("от" и "до"). Если интервал не нужен и необходим вывод только одного элемента формы, то нужно использовать данный метод.
- filterValuesList($field, $params) - для полей типа "enum" (с внешним ключом) ), "parent" и "many_to_many" есть возможность фильтрации списка значений, используя параметры в формате Конструктор запросов, $field - название поля, $params - массив параметров для фильтрации и/или упорядочивания.
- addOptionToValuesList($field, $value, $title) - для полей типа "enum" и "parent" дает возможность добавить значение в список опций.
- setDisplaySingleField($field) - для полей типа "date","date_time","int","float","order" задает опцию, при которой поле будет выведено как как одно текстовое поле, а не интервал из двух полей. Также, фильтр будет принимать значение в виде единственного GET параметра, вместо интервальных значений "from" и "to".
- setDisplayCheckbox($field) - для полей типа "bool","image","file","multi_images" задает опцию отображения в виде элемента checkbox, в результате вызова функции display()
- setDisplayEnumRadio($field, $columns) - для полей типа "enum" задает опцию вывода html кода в виде таблицы с кнопками radio, параметр $columns задает количество колонок в таблице.
- setDisplayEnumCheckboxes($field, $columns, [$empty_checkbox]) - для поля типа "enum" задает возможность отображения списка значений в виде таблицы с чекбоксами. Параметры $field - название поля, $columns - количество колонок в таблице, $empty_checkbox - необязательный параметр, показывающий надо ли отображать первым в списке чекбокс с пустым значением (например для производителей "Все производители"). Выводит html таблицу с полями checkbox. Таким образом можно организовать множественный выбор. Фильтр для данного поля в таком случает отдаст значение вида "2,7,24".
- setDisplayCheckboxTable($field, $columns) - для полей типа "many_to_many" задает отображение в виде таблицы с чекбоксами аналогично предыдущему методу. Без вызова данного метода поле "many_to_many" отображаться в фильтрах не будет.
- setManyToManyEmptyValueTitle($field, $title) - для полей типа "many_to_many" задает подпись для пустого значения, когда фильтр отображается тэгом "select".
//Получение значений фильтров $mv -> furniture -> filter -> getValue("location"); $mv -> furniture -> filter -> getValue("price", "from"); $mv -> furniture -> filter -> getValue("price", "to"); //Добавление параметров фильтрации к URL $path = $mv -> root_path."search/?page=3"; $path = $mv -> furniture -> filter -> addUrlParams($path); //Метод отображения нужных записей с учетом фильтрации class Furniture extends Model { ... public function display() { //Массив условий заданных фильтров $conditions = $this -> filter -> getConditions(); $conditions["active"] = 1; $rows = $this -> select($conditions); ... } } //Если хотя бы один фильтр установлен if($mv -> furniture -> filter -> hasParams()) { ... } //Задание подписи для пустого значения поля "enum" $mv -> furniture -> filter -> setEnumEmptyValueTitle("location", "Выберите расположение"); echo $mv -> furniture -> filter -> display("location"); //Сделаем возможность множественного выбора для поля "Расположение" $mv -> furniture -> filter -> setDisplayEnumCheckboxes("location", 2); //Зададим отображение поля в виде radio кнопок в 3 столбца $mv -> furniture -> filter -> setDisplayRadio("location", 3); //Поле "Активен" будем выводить как checkbox $mv -> furniture -> filter -> setDisplayCheckbox("active"); //Поле цены выводим как одиночное поле для задания значения без интервала $mv -> furniture -> filter -> setDisplaySingleField("price"); //Выводим все поля фильтра со всеми заданными опциями echo $mv -> furniture -> filter -> display(); //Отображение списка фильтров в шаблоне //После отправки формы значения попадут в GET строку и их примет объект $mv -> furniture -> filter //Далее в классе Furniture можно будет воспользоваться значениями фильтров как было описано выше <form class="filters-list" method="get" action="<? echo $mv -> root_path; ?>my-page-url/"> <? echo $mv -> furniture -> filter -> display(); ?> <input type="submit" value="Найти" /> </form>
Примечания и рекомендации
- В результате вызова метода "getConditions()" возвращается набор условий, которые конструктор запросов свяжет между собой через "И", при этом если для полей типа "enum" и "many_to_many" задается множественный выбор в виде таблицы с чекбоксами, то вернется конструкция вида "field->in" => "8,25,87", что говорит о связи для данного поля через "ИЛИ".
- Поля типа "date","date_time","int","float","order" фильтруют по интервалам "от" и "до". При вызове метода "display()" для такого поля возвращается 2 текстовых поля формы для задания интервала ("from", "to"). Например в модели "Furniture" для поля "price" будут выведены поля с именами "price-from" и "price-to". Если нужно вывести одно общее поле без интервалов, то используется метод "displaySingleField()".
- Поле вида Многие ко многим изначально будет отображаться в результате вызова метода "display()" в виде элемента select с возможностью выбора одного значения. Если же для поля задано отображение в виде чекбоксов методом "setDisplayCheckboxTable($field, $columns)", то будет отображаться список чекбоксов с возможностью множественного выбора.
- Если в фильтре одной модели есть 2 и более полей типа "many_to_many" результат вызова метода "getConditions()" для всех этих полей все равно вернет 1 конструкцию вида "id->in" => "3,6,23". При этом в списке найденных id уже будут учтены "пересечения" всех фильтров для полей "many_to_many". Если в результате "пересечения" фильтров "many_to_many" записей не найдено, то вернется конструкция "id->in" => "0", что говорит о том что записей, удовлетворяющих всем условиям фильтров нет.
- Для полей типа "image","file","multi_images" метод "getConditions()" возвращает конструкцию "field->like" => ".", что при SQL запросе будет являться проверкой на наличие пути файла в ячейке SQL таблицы, при этом если необходимо проверить наличие реального файла на диске, нужно использовать функции php.
Предыдущий раздел
Сортировка