Фильтрация разделов по свойству элементов - список без пустых
Показываем в меню только те разделы, где действительно есть товары нужного бренда или в наличии, и убираем из списка пустые.
Решение
Собираем разделы по элементам:
$rows = CIBlockElement::GetList( [], ['IBLOCK_ID' => 12, 'ACTIVE' => 'Y', 'PROPERTY_BRAND' => $brandId], ['IBLOCK_SECTION_ID'], // группировка: разделы с числом подходящих товаров);// прямого фильтра «разделы по свойству элемента» в платформе нет:// значения свойств и разделы лежат в разных таблицахРазделы собирают по элементам, а не запросом к самим разделам. Свойства принадлежат элементу, поэтому путь всегда один: сначала подходящие товары, потом их разделы.
Показываем найденные разделы:
$sectionIds = array_column($rows, 'IBLOCK_SECTION_ID');$res = CIBlockSection::GetList(['SORT' => 'ASC'], ['IBLOCK_ID' => 12, 'ID' => $sectionIds, 'ACTIVE' => 'Y'], false, ['ID', 'NAME', 'SECTION_PAGE_URL']);while ($section = $res->GetNext()) { printf('<a href="%s">%s</a>', $section['SECTION_PAGE_URL'], $section['NAME']);}Отбор идёт по списку номеров, полученному на первом шаге. Сортировку и адреса при этом отдаёт уже запрос к разделам, и порядок в меню остаётся привычным.
Дотягиваем родительские разделы:
foreach ($sectionIds as $id) { $nav = CIBlockSection::GetNavChain(12, $id, ['ID'], true); $sectionIds = array_merge($sectionIds, array_column($nav, 'ID'));}$sectionIds = array_unique($sectionIds); // иначе верхний уровень меню опустеетТовар лежит в подразделе, а показать обычно нужно и его родителя. Без этого шага меню верхнего уровня оказывается пустым при полном каталоге товаров ниже.
Считаем ответ заранее на большом каталоге:
// агент раз в час: складываем признак прямо в поле раздела$brands = implode(',', $brandIdsInSection);CIBlockSection::Update($sectionId, ['UF_BRANDS' => $brands]);// дальше меню строится одним запросом к разделам, без обхода элементовНа каталоге в сотни тысяч позиций обход элементов при каждом показе слишком дорог. Признак кладут в поле раздела и пересчитывают по расписанию, а меню строится одним запросом.
Список разделов стоит кэшировать вместе с тегом инфоблока. Тогда обмен с учётной системой сбрасывает его сам, и меню не показывает вчерашний набор разделов после ночной выгрузки.
Пустые разделы полезно убирать из меню, а не прятать стилями. Скрытая ссылка всё равно попадает в карту сайта и в выдачу, и покупатель приходит на страницу без единого товара.
Правило отбора стоит держать в одном месте кода. Меню, карта сайта и фильтр обязаны отвечать одинаково, иначе покупатель видит раздел в меню и не находит его в фильтре.
Задачу стоит начинать с вопроса, сколько разделов и товаров в каталоге на самом деле. На двух сотнях разделов подойдёт любой из способов, а на десяти тысячах разница между ними измеряется секундами ожидания покупателя.
Типичные проблемы
Раздел с товарами не попал в список.
Группировка идёт по основному разделу, а товар привязан к нему дополнительно. Множественную привязку читают отдельным запросом.
Верхний уровень меню оказался пустым.
Товары лежат в подразделах, а собраны только их прямые разделы. Родительские разделы дотягивают цепочкой вверх.
Список разделов строится по нескольку секунд.
При каждом показе обходятся все элементы каталога. На больших объёмах признак считают заранее и хранят в разделе.
После обмена меню показывает старые разделы.
Список закэширован без привязки к данным инфоблока. Кэш помечают тегом, и обмен сбрасывает его сам.
В выдаче есть разделы без товаров.
Пустые разделы скрыты стилями, а не убраны из списка и карты сайта. Прятать нужно на уровне данных.
Частые вопросы
Можно ли отфильтровать разделы одним запросом?
Нет: свойства принадлежат элементам, а не разделам. Путь всегда через выборку элементов.
Как учесть товары в подразделах?
Дотянуть цепочку родителей вверх или считать признак с учётом вложенности. Второе дороже, но точнее.
Подходит ли для этого умный фильтр?
Он решает задачу внутри раздела, а не отбор самих разделов. Для меню нужен свой расчёт.
Когда переходить на поле-агрегат?
Когда обход элементов перестаёт укладываться в доли секунды. Обычно это десятки тысяч товаров.
Смежное
- Свойства инфоблоков - оглавление подтемы
- Свойства инфоблока: чтение, запись и фильтрация по значению - отбор элементов по свойству
- Вывод разделов: дерево, подразделы, адреса - обычный вывод дерева
- Кэширование своей выборки: ключ, теги, сброс - как закэшировать такой список
- Инфоблоки - устройство хранилища целиком