Свойства-привязки - элемент, раздел и обратная выборка
Разбираем свойства типа привязка: чем они отличаются от списков, как выводить названия без лишних запросов и как искать по ним в обе стороны.
Решение
Смотрим, что лежит в свойстве привязки:
$res = CIBlockElement::GetList([], ['IBLOCK_ID' => 5, 'ID' => $elementId], false, false, ['ID', 'NAME', 'PROPERTY_BRAND', 'PROPERTY_RELATED']);$row = $res->Fetch();var_dump($row['PROPERTY_BRAND_VALUE']); // идентификатор элемента-брендаvar_dump($row['PROPERTY_RELATED_VALUE']); // массив, если свойство множественноеВ привязке хранится идентификатор элемента, а не его название. Это и отличает её от списка: значения живут отдельным инфоблоком со своими свойствами, картинками и правами, а свойство лишь ссылается на них.
Выводим названия одним запросом на весь список:
$ids = array_filter(array_column($rows, 'PROPERTY_BRAND_VALUE'));$names = [];$res = CIBlockElement::GetList([], ['IBLOCK_ID' => 8, 'ID' => $ids], false, false, ['ID', 'NAME']);while ($b = $res->Fetch()) { $names[$b['ID']] = $b['NAME']; // один запрос вместо запроса на каждый товар}Запрос названия внутри цикла по товарам - самая частая причина медленной витрины. Собранный список идентификаторов забирают одним запросом, а дальше берут названия из готового массива.
Фильтруем выборку по значению привязки:
$filter = ['IBLOCK_ID' => 5, 'ACTIVE' => 'Y', 'PROPERTY_BRAND' => $brandId];$res = CIBlockElement::GetList(['SORT' => 'ASC'], $filter, false, ['nPageSize' => 20], ['ID', 'NAME']);// фильтр принимает идентификатор; по названию бренда отбор здесь не работаетФильтр по привязке работает только по идентификатору. Название сначала переводят в идентификатор отдельным запросом, и это же правило действует для адресов раздела с параметром бренда.
Находим разделы, где такие элементы есть:
$sections = [];$res = CIBlockElement::GetList([], ['IBLOCK_ID' => 5, 'PROPERTY_BRAND' => $brandId, 'ACTIVE' => 'Y'], false, false, ['ID', 'IBLOCK_SECTION_ID']);while ($e = $res->Fetch()) { $sections[$e['IBLOCK_SECTION_ID']] = true; // ключи массива снимают повторы}Обратная задача решается от элементов к разделам, а не наоборот. Прямого фильтра разделов по свойствам их элементов нет, и попытка собрать такой список средствами выборки разделов заканчивается ничем.
Привязка к разделу устроена так же, но ссылается на раздел:
$res = CIBlockSection::GetList([], ['IBLOCK_ID' => 5, 'ID' => $row['PROPERTY_LINE_VALUE']], false, ['ID', 'NAME', 'SECTION_PAGE_URL']);$line = $res->GetNext(); // GetNext сразу приводит поля к выводуecho $line['NAME'];Разница только в том, откуда берутся значения. Проверка на существование нужна обеим: удалённый элемент или раздел оставляет в свойстве идентификатор, которому уже ничего не соответствует.
Привязку удобно заводить сразу, если у значения есть хоть какое-то описание. Перевод свойства из списка в привязку на живом каталоге означает перенос всех значений отдельным скриптом и пересохранение каждого элемента.
Множественная привязка возвращает массив даже с одним значением. Код, который ждёт строку, на таком свойстве ломается молча: в вывод попадает слово «массив» вместо названия.
Типичные проблемы
В шаблоне выводится число вместо названия.
Свойство хранит идентификатор элемента. Название забирают отдельным запросом по этому идентификатору.
Витрина стала медленной после вывода бренда.
Название запрашивается внутри цикла по товарам. Идентификаторы собирают в список и делают один запрос.
Фильтр по названию бренда ничего не находит.
Фильтр по привязке принимает идентификатор. Название переводят в идентификатор отдельным запросом.
В карточке пустое место вместо привязки.
Элемент, на который она ссылалась, удалён или выключен. Идентификатор в свойстве при этом остаётся прежним.
Не удаётся отобрать разделы по свойству элементов.
Такого фильтра у разделов нет. Список собирают из разделов найденных элементов.
Частые вопросы
Чем привязка лучше списка?
У значения появляются свои свойства, картинка и страница. Список хранит только текст, и расширить его нечем.
Можно ли привязаться к элементу другого инфоблока?
Да, инфоблок-источник задаётся в настройках свойства. Без указания источника выбор идёт по всем инфоблокам сразу.
Как вывести список товаров бренда на его странице?
Выборкой товаров с фильтром по привязке, где значением стоит идентификатор текущего элемента. Это обычный список каталога с дополнительным условием.
Почему привязка не видна в умном фильтре?
Свойство не включено в настройки фильтрации у инфоблока. Умный фильтр показывает только отмеченные там свойства.
Смежное
- Свойства инфоблоков - оглавление подтемы
- Свойства инфоблока: чтение, запись и фильтрация по значению - работа со свойствами целиком
- Множественные свойства: вывод файлов, фильтр, удаление значений - когда значений несколько
- Выборки из инфоблоков: GetList, ORM и разделы - как устроены сами выборки
- Инфоблоки - устройство инфоблоков целиком
- Highload-блок на практике: создание, поля, привязка к свойству - справочник вместо привязки к элементу
- Отзывы о товаре: хранение, модерация, средняя оценка - привязка отзыва к товару