Описание метода работы
Для реализации адаптивного фильтра необходимо использовать две выборки.
Первая (начальная, исходная) выбирает все активные и не удаленные товары из текущей группы, без учета пейджинга, сортировки и пользовательских фильтров.
Вторая (конечная, фильтрованная) выбирает из первой выборки те товары, которые удовлетворяют условиям, наложенным пользовательскими фильтрами.
По каждой выборке мы можем вычислить
- границы диапазона цен,
- допустимые значения некоторых основных (производитель, продавец) и дополнительных (имеющих тип Список и способ отображения в фильтре "Список ..."
свойств,
- а также границы диапазона значений некоторых доп.свойств (имеющих тип число и способ отображения в фильтре "От ... до ..."
В текущей базовой логике HostCMS это потребовало бы тройной нагрузки на базу данных -
а) сначала мы в рамках работы с расширенной работы со свойствами выполнили бы запрос первой выборки,
б) затем, с той же целью - второй выборки,
в) а после этого show-метод внутри себя выполнил бы запрос второй выборки еще раз, уточнив его сортировкой и лимитом.
При этом, из-за уточнения на сортировку и лимит, кеш БД равно как и кеш системы, при повторном выполнении запроса не эффективен.
Собственно, так и было в аналогичной разработке для HostCMS v.5
При этом надо учесть, что второй и третий запрос довольно тяжелые и существенно замедляют генерацию страницы
Поэтому целесообразно разбить тяжелый второй запрос на два простых, а запрос из show-метода максимально упростить.
Схема работы данного контроллера с базой данных следующая:
1. Когда мы вызываем метод processFilters(), то в первую очередь выполняем запрос исходной выборки, получая только id товаров попадающих в нее. Этот запрос легкий, с точки зрения нагрузки на БД
2. Далее мы удаляем все условия в Shop_Items->QueryBuilder и заменяем их на единственное условие shop_items.id IN (<идентификаторы товаров, попавших в исходную выборку>
3. После этого мы вносим в Shop_Items->QueryBuilder все условия, которые обусловлены пользовательскими фильтрами Поскольку при этом не надо предварительно отбирать сами товары по сложным условиям, то запрос выполняется быстро, заметно быстрее, чем "классический" запрос с фильтрами в методе show() вызванном из ТДС. Здесь мы тоже получаем только id товаров, но это уже вторая выборка, с учетом фильтров
4. Затем мы снова удаляем все условия в Shop_Items->QueryBuilder и опять заменяем их на единственное условие shop_items.id IN (<но уже идентификаторы товаров, попавших в конечную выборку>
и восстанавливаем сортировку и лимит.
Таким образом, мы избегаем повторного выполнения тяжелого запроса внутри show-метода.
Контроллер поддерживает два способа выдачи результатов обработки фильтров:
- в виде json-строки;
- в виде XML-фрагмента, который автоматически добавляется к XML-документу контроллера.
В обоих случаях, результаты имеют одинаковую структуру.
Результат состоит из трех секций:
- used - значения фильтров, переданные через get-запрос от пользователя сайта
- initial - значения цен, свойств и доп.свойств для начальной выборки
- filtered - значения цен, свойств и доп.свойств для фильтрованной выборки
Внутри каждой секции могут быть следующие элементы:
- count - общее число товаров в выборке (без учета модификаций)
- count_total - общее число товаров в выборке с учетом модификаций (UPD для v1.4g+)
- sorting - содержит текущую сортировку
- producer_id - содержит идентификатор(ы) производителей
- seller_id - содержит идентификатор(ы) продавцов
- price - границы диапазона цен товаров (содержит массив как минимум с одним из элементов from или to)
- property_values - значения доп.свойств (содержит массив, ключами которого являются id доп.свойств, а значениями - массивы значений этих доп.свойств)
- property_ranges - границы диапазонов значений доп.свойств для диапазонных доп.свойств (содержит массив, ключами которого являются id доп.свойств, а значениями - массивы как минимум с одним из элементов from или to)