Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Добрый день, прошу советов относительно реализации каталога товаров. Не получилось найти материалы в сети, которые бы мне помогли. Нужный мне функционал можно посмотреть тут: http://hotline()ua/computer/planshety/
Сразу приношу извинения, но кода не будет, только логика.
Функционал заведомо упрощен, без групп фильтров, категорий товаров, пагинации, и другого.
Есть список товаров (id, title, price, ...), список фильтров (id, title, suffix) и список элементов фильтров (id, filter_id, value) и связующая таблица (id, item_id, value_id).
Моя реализация работает так, при клике на элемент фильтра, который является ссылкой, генерируется запрос cо списком id всех задействованных элементов. Этот список парситься в массив, и с помощью where_in тянуться все задействованные элементы, первый запрос.
Жадно грузим все товары для этих элементов, второй запрос. После чего генерируем массив массивов из id этих товаров. Используем условие, что если элементы относятся к одному фильтру, id их товаров сливаются. На выходе массив вида: id фильтра => массив id товаров.
Получаем схождение этих массивов, и подставляем результат в where_in, получая все нужные товары, это третий запрос.
Теперь нужно сгенерировать фильтры. Грузим фильтры, жадно грузим их элементы. Четвертый и пятый запросы.
Выводим фильтра и их элементы, генерируя ссылки. Ссылки генерируються в зависимости присутствия id элемента в массиве получаемого из запроса. Если отсутствует, добавляем к этому запросу и подставляем в ссылку, если присутствует, убираем из запроса и подставляем в ссылку, присваивая ссылке класс.
Теперь о предварительном подсчете результатов. После каждого элемента в скобках присутствует число, которое показывает как измениться количество подходящих товаров после применения этого фильтра. Если из элементов этого фильтра нет ни одного активного, то просто число, которое показывает количество товаров (17). Но если уже хоть один элемент активен, это число со знаком плюс, которое показывает сколько товаров добавиться к текущему количеству (+8). Если такое число ноль, элемент не выводиться. Сложно объяснить, лучше посмотреть образец, который я привел выше.
Начиная с этого места, я очень сомневаюсь. Жадно загрузить count с динамическим запросом не получиться.
Можно делать отдельный count запрос для каждого элемента, подставляя в условие скорректированный массив id товаров, полученный выше. Это ~много~ запросов, что меня огорчает. Можно жадно загрузить все относящиеся к элементу товары. И потом уже сравнивать массив их id с вышеупомянутым массивом. Это один запрос, но быстрее ли он первого варианта. Так же, теоретически, можно отойти от отношений и вручную использовать join, но этот вариант я пока не обдумывал.
Собственно интересует каким путем пошли бы вы? Рад буду если вы поделитесь опытом. Заранее спасибо!
Не в сети
- Можно делать отдельный count запрос для каждого элемента, подставляя в условие скорректированный массив id товаров, полученный выше.
Это оптимальный вариант, причём можно сделать одним запросом. Есть такая штука как GROUP_CONCAT — она работает для аггрегирующих запросов (с AVG(), COUNT(), SUM() и прочими) и позволяет объединить в строку значения одного/нескольких полей как PHPjoin('-', $columns);
в PHP/
Поэтому твой запрос можно сформировать так:
sqlSELECT COUNT(1), GROUP_CONCAT(DISTINCT product_id ORDER BY product_id) FROM products WHERE product_id IN (товары, по, фильтру, №1) OR product_id IN (товары, по, фильтру, №2) OR ...
Не в сети
Спасибо за ответ! Но, насколько я понял, такой подход предполагает отдельный запрос для каждого элемента фильтра. Это подход быстрее чем один запрос, а затем манипуляция с массивами, я правильно понял? Если же, вы имели в виду, вообще один запрос сразу для всех элементов, я правда, не понимаю как можно выстроить такую конструкцию в Fluent.
Не в сети
- Если же, вы имели в виду, вообще один запрос сразу для всех элементов, я правда, не понимаю как можно выстроить такую конструкцию в Fluent.
Через PHPDB::raw()
для GROUP_CONCAT. В кратце схема такая:
PHP'IN '.join(', ', $ids)
Выполняется один запрос. Разбор результата должен быть довольно быстрым.
Не в сети
Спасибо, попробую!
Не в сети
Страницы 1