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

Справочник в выборках - вывод значений, фильтр, кэш

Выводим бренды и характеристики из справочника так, чтобы список товаров не превращался в сорок отдельных запросов к его таблице.

Решение

Достаём названия одним запросом:

$codes = array_column($items, 'PROPERTY_BRAND_VALUE'); // коды со всех товаров
$rows = $dataClass::getList([
'select' => ['UF_XML_ID', 'UF_NAME'],
'filter' => ['@UF_XML_ID' => array_unique($codes)],
])->fetchAll();
$names = array_column($rows, 'UF_NAME', 'UF_XML_ID'); // код к названию

Названия справочника берут одним запросом на весь список. Обращение к справочнику внутри цикла по товарам даёт сорок запросов на страницу витрины, и это самая частая причина её медленной работы.

Фильтруем каталог по значению справочника:

$filter = ['IBLOCK_ID' => 12, 'ACTIVE' => 'Y', 'PROPERTY_BRAND' => 'acme'];
// свойство хранит внешний код записи справочника, а не её название
// фильтр по названию не найдёт ничего: названия в свойстве нет вовсе

Свойство хранит код записи, а не её название. Отсюда правило: фильтруют по коду, а название достают отдельно и только для показа.

Пересобираем индекс после заливки:

$indexer = new \Bitrix\Iblock\PropertyIndex\Indexer($iblockId);
$indexer->startIndex();
// новые значения справочника появятся в умном фильтре только после этого

Значения появляются в фильтре после пересборки индекса. Справочник залили, товарам проставили бренды, а фильтр показывает старый список - это ровно тот случай.

Кэшируем справочник целиком:

if ($cache->initCache(86400, 'brands_' . $hlId, '/vendor/hl')) {
$names = $cache->getVars();
} elseif ($cache->startDataCache()) {
$names = self::loadAll($dataClass); // весь справочник в память
$cache->endDataCache($names);
}

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

Сбрасывать такой кэш нужно при правке справочника, а не по времени. Сутки со старым названием бренда после переименования - неприятная мелочь, которую никто не связывает с кэшем.

Справочник не заменяет собой свойство типа «список» на совсем маленьких наборах. Три значения проще держать списком: справочник окупается там, где записей сотни и у них есть свои поля.

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

Справочник стоит заводить с прицелом на то, что его будут заливать обменом. Внешний код записи в этом случае - главное поле: по нему обмен находит уже существующие записи и не плодит их копии при каждой выгрузке.

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

Страница списка товаров стала медленной.

Название справочника достаётся отдельным запросом на каждый товар. Названия берут одним общим запросом сразу по всему списку уже собранных кодов.

Фильтр по бренду ничего не находит.

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

Новые значения не появились в умном фильтре.

Фасетный индекс не пересобран после этой массовой заливки самого справочника. Пересборку фасетного индекса ставят сразу следом за массовой заливкой всего справочника.

У части товаров бренд пустой.

У записей справочника попросту не заполнен их собственный внешний код записи. Свойство хранит именно этот код, и без кода связь просто не сохраняется.

После переименования бренда на витрине старое название.

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

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

Как показать название вместо кода?

Через свойство типа «справочник» в компоненте: он подставит название сам. В своей выборке название берут отдельным запросом.

Можно ли фильтровать по полю справочника?

Только через свои выборки: сначала коды нужных записей, потом фильтр по ним. Умный фильтр работает по коду.

Что быстрее: справочник или свойство-список?

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

Как найти неиспользуемые записи?

Сравнить коды справочника с набором значений свойства у товаров. Разница - кандидаты на удаление.

Смежное

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