Перейти к содержимому

Витрина каталога - список раздела, сортировка, фильтр

Выводим товары раздела на витрину, задаём порядок и фильтр и разбираемся, почему часть товаров в список не попадает.

Решение

Выводим товары раздела:

$APPLICATION->IncludeComponent('bitrix:catalog.section', '', [
'IBLOCK_TYPE' => 'catalog',
'IBLOCK_ID' => 5,
'SECTION_CODE' => $sectionCode, // код раздела из адреса страницы
'INCLUDE_SUBSECTIONS' => 'Y', // товары подразделов тоже в списке
'ELEMENT_SORT_FIELD' => 'SORT',
'ELEMENT_SORT_ORDER' => 'ASC',
'PRICE_CODE' => ['BASE'], // без него цены в результат не попадут
'PROPERTY_CODE' => ['MATERIAL', 'COLOR'],
'PAGE_ELEMENT_COUNT' => 20, // размер страницы для навигации по списку
]);

Компонент выбирает товары только своего раздела. Товар, лежащий в соседнем разделе, в списке не появится, даже если карточка у него открывается.

Задаём порядок сортировки:

'ELEMENT_SORT_FIELD' => 'PROPERTY_PRIORITY', // сортировка по свойству
'ELEMENT_SORT_ORDER' => 'DESC',
'ELEMENT_SORT_FIELD2' => 'NAME', // вторая пара разрешает ничьи
'ELEMENT_SORT_ORDER2' => 'ASC',

Вторая пара полей нужна почти всегда. Без неё товары с одинаковым значением первого поля выстраиваются в произвольном порядке, и он меняется от запроса к запросу.

Сортировка по числовому свойству требует правильного типа. У свойства типа «строка» значения сравниваются посимвольно, и 100 оказывается раньше 20. Числовой порядок даёт только свойство числового типа.

Фильтруем выборку по свойству:

// в init.php или в файле страницы, до вызова компонента
$GLOBALS['catalogFilter'] = ['PROPERTY_MATERIAL_VALUE' => 'дерево'];
// в параметрах компонента передаётся имя переменной, а не массив
'FILTER_NAME' => 'catalogFilter',

Компонент читает глобальную переменную с указанным именем. Массив, переданный в параметр напрямую, он игнорирует молча: список выводится без фильтрации, и ошибки в логе нет.

Выводим подразделы над списком товаров:

$APPLICATION->IncludeComponent('bitrix:catalog.section.list', '', [
'IBLOCK_ID' => 5,
'SECTION_CODE' => $sectionCode,
'VIEW_MODE' => 'LINE',
'SHOW_PARENT_NAME' => 'N',
]);

Список товаров о подразделах ничего не знает: это два разных компонента и две разных выборки. Раздел с подразделами и без собственных товаров поэтому выглядит пустой страницей, пока второй компонент не поставлен рядом с первым.

Ограничиваем выборку постраничной навигацией:

'PAGE_ELEMENT_COUNT' => 24, // сколько товаров на странице витрины
'LINE_ELEMENT_COUNT' => 3,
'CACHE_TIME' => 36000,
'CACHE_GROUPS' => 'N', // одинаковый кэш для всех групп посетителей

Каталог на десятки тысяч позиций без ограничения по странице выбирает всё сразу и упирается в память. Кэш здесь снимает нагрузку с базы, но раздельный кэш на каждую группу пользователей размножает файлы и съедает выигрыш.

Товар может лежать сразу в нескольких разделах, и это штатное поведение платформы. Основным считается тот раздел, который указан в поле привязки первым: по нему собирается адрес карточки товара. Остальные разделы показывают товар в своих списках, но ссылка из каждого ведёт на один и тот же адрес.

Типичные проблемы

Товары есть в админке, но витрина пуста.

Они не привязаны к разделу либо привязаны к другому. Список раздела выбирает строго по привязке, а админка показывает все элементы инфоблока сразу.

Порядок товаров меняется сам собой.

Не задана вторая пара полей сортировки. При равных значениях первого поля порядок определяет база, и он не гарантирован.

Сортировка по числу идёт как по строке.

Свойство заведено строкой. Значения сравниваются посимвольно, поэтому 100 встаёт перед 20.

Фильтр не действует, список полный.

В параметр передан массив вместо имени переменной. Компонент ищет глобальную переменную с этим именем и не находит её.

В разделе не видно подразделов.

Стоит только компонент списка товаров. Подразделы выводит отдельный компонент, и его добавляют явно.

Частые вопросы

Как вывести товары из всех разделов сразу?

Не передавать код раздела: тогда компонент выбирает по всему инфоблоку. Для большого каталога это тяжёлая выборка, и её ограничивают постраничной навигацией.

Можно ли положить товар в несколько категорий?

Да, через дополнительную привязку к разделам. Основным остаётся первый: по нему собирается адрес карточки, а остальные показывают товар в своих списках.

Почему у товаров нет цены на витрине?

Не заполнен параметр с типами цен. Компонент выбирает только перечисленные типы, а без них отдаёт элементы вовсе без цен.

Как отсортировать товары без цены в конец?

Штатной сортировкой это не делается: цена приходит отдельной выборкой. Порядок задают своим свойством, которое заполняется при выгрузке.

Смежное

Первоисточник