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

Инфоблок через ORM - API_CODE, класс элементов, свойства

Работаем с элементами инфоблока через слой данных: символьный код для API, класс сущности, чтение и запись свойств, множественные значения.

Что нужно знать заранее

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

Базовый класс элементов напрямую не используют ни в одном сценарии. Он видит только общие поля всех инфоблоков, а свойства и связи живут в собранной сущности конкретного инфоблока.

В карту сущности попадают только свойства с заполненным символьным кодом свойства. Свойство без кода видно в админке и в старом интерфейсе, но объектам оно недоступно совсем.

Шаги

  1. Заполнить инфоблоку символьный код для программного интерфейса прямо в его настройках в админке.
  2. Проверить, что у всех нужных свойств инфоблока заполнены символьные коды латиницей.
  3. Сбросить кэш сайта после правки кода, чтобы сущность инфоблока собралась заново.
  4. Получить класс сущности по идентификатору инфоблока и дальше работать только через него.
  5. Для множественных свойств использовать добавление значения, а не присваивание всего набора.

Решение

Задаём инфоблоку код для программного интерфейса:

\Bitrix\Main\Loader::includeModule('iblock');
$iblock = new \CIBlock();
$iblock->Update($iblockId, ['API_CODE' => 'News']); // латиница, с большой буквы
// имя класса собирается из этого кода: ElementNewsTable
// после правки сбрасывают кэш: сущность собирается заново

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

Берём класс сущности по идентификатору:

$entity = \Bitrix\Iblock\Iblock::wakeUp($iblockId)->getEntityDataClass();
$rows = $entity::getList(['select' => ['ID', 'NAME'], 'filter' => ['=ACTIVE' => 'Y']])->fetchAll();
// так код не зависит от имени класса и переживает переименование кода инфоблока

Обращение по идентификатору удобнее прямого имени класса. Идентификатор берут из настроек проекта, и один и тот же код работает на стенде и на боевом сайте, где номера инфоблоков различаются.

Читаем свойства объектами:

$element = \Bitrix\Iblock\Elements\ElementNewsTable::getList([
'select' => ['ID', 'NAME', 'AUTHOR'], // свойство перечисляем явно
'filter' => ['=ID' => $id],
])->fetchObject();
echo $element->getAuthor()->getValue(); // значение свойства приходит объектом

Значение свойства приходит не строкой, а объектом значения. Это позволяет добраться и до самого значения, и до описания, но требует привычки: прямое сравнение объекта со строкой не работает.

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

$rows = \Bitrix\Iblock\Elements\ElementNewsTable::getList([
'select' => ['ID', 'NAME'],
'filter' => ['=SECTION_TYPE.VALUE' => 'Анонс'], // фильтр идёт по значению варианта
])->fetchAll();
// сравнение с текстом вместо значения варианта не даёт ни одной строки

Списочное свойство хранит идентификатор варианта, а не его текст. Фильтр по значению варианта - штатный способ, а попытка сравнить с подписью варианта возвращает пустую выборку.

Пишем множественное свойство:

$element = \Bitrix\Iblock\Elements\ElementNewsTable::getByPrimary($id)->fetchObject();
$element->addToTags($valueId); // добавление значения, а не присваивание
$element->save();
// присваивание у множественного свойства затирает уже сохранённые значения

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

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

Ошибка об отсутствующем классе элементов.

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

Свойство не видно у объекта элемента.

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

Фильтр по списочному свойству ничего не находит.

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

После записи множественного свойства старые значения исчезли.

Значение присвоено целиком вместо добавления к уже существующему набору. У множественных свойств пользуются добавлением значения, а не присваиванием набора.

Класс элементов перестал существовать после правки настроек.

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

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

Обязателен ли переход на объекты?

Нет, старый интерфейс выборок продолжает работать и никуда не денется. Объекты берут для нового кода, где важны типы значений и работа со связями.

Где взять имя класса элементов?

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

Что делать со свойствами без кода?

Заполнить код и сбросить кэш: только после этого свойство появится у объектов. Данные при заполнении кода не теряются.

Работают ли права доступа при таких выборках?

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

Можно ли смешивать оба интерфейса?

Да, они работают с одними и теми же данными. В одном участке кода лучше держаться одного стиля, иначе читать такой код тяжело.

Смежное

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