Битрикс

API инфоблоков в Битрикс D7

В 20 версии Битрикс спустя несколько лет после появления ядра D7, призванного превратить Битрикс в современный фреймворк (нет), появилась возможность хоть как-то удобно использовать новое ядро для работы с элементами инфоблоков и их свойствами.

Примеры протестированы на версии 1С-Битрикс: Управление сайтом 20.0.1196. Кстати, не забываем подключить модуль iblock:

\Bitrix\Main\Loader::includeModule('iblock');

Для доступа к возможностям нового ядра у инфоблока нужно задать так называемый Символьный код API. По документации это строка от 1 до 50 символов, начинающаяся с буквы и состоящая из латинских букв и цифр.

iblock.png

Для работы с элементами используется класс \Bitrix\Iblock\Elements\ElementXXXXXTable, где XXXXX - Символьный код API. Для инфоблока на примере выше это будет класс \Bitrix\Iblock\Elements\ElementCatalogTable. Получить название класса для инфоблока можно следующим методом:

var_dump(\Bitrix\Iblock\Iblock::wakeUp($iblockId)->getEntityDataClass());
// string(43) "\Bitrix\Iblock\Elements\ElementCatalogTable"

Работа с элементом как с массивом

Разберем различные примеры получения элементов. Простейший пример - это аналог CIBlockElement::GetByID:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getByPrimary($elementId, [
    'select' => ['ID', 'NAME', 'DETAIL_TEXT', 'DETAIL_PICTURE', 'ARTNUMBER'],
])->fetch();
var_dump($element);
/*array(8) {
  ["ID"]=>
  string(1) "4"
  ["NAME"]=>
  string(38) "Штаны Полосатый Рейс"
  ["DETAIL_TEXT"]=>
  string(?) "Брюки-клеш идеально сидят..."
  ["DETAIL_PICTURE"]=>
  string(2) "46"
  ["IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_ID"]=>
  string(1) "9"
  ["IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_IBLOCK_ELEMENT_ID"]=>
  string(1) "4"
  ["IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_IBLOCK_PROPERTY_ID"]=>
  string(1) "9"
  ["IBLOCK_ELEMENTS_ELEMENT_CATALOG_ARTNUMBER_VALUE"]=>
  string(11) "177-77-хх"
}*/

Да, указывается код свойства без префикса "PROPERTY". Правда здесь выходит какое-то безумное именование ключей. Немного получше можно сделать с помощью алиасов:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getByPrimary($elementId, [
    'select' => ['ID', 'NAME', 'ARTNUMBER_' => 'ARTNUMBER'],
])->fetch();
var_dump($element);
/* 
array(6) {
  ["ID"]=>
  string(1) "4"
  ["NAME"]=>
  string(38) "Штаны Полосатый Рейс"
  ["ARTNUMBER_ID"]=>
  string(1) "9"
  ["ARTNUMBER_IBLOCK_ELEMENT_ID"]=>
  string(1) "4"
  ["ARTNUMBER_IBLOCK_PROPERTY_ID"]=>
  string(1) "9"
  ["ARTNUMBER_VALUE"]=>
  string(11) "177-77-хх"
}
*/

Аналогом CIBlockElement::GetList будет getList из D7:

$elements = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'NAME', 'ARTNUMBER_' => 'ARTNUMBER'],
    'filter' => ['=ACTIVE' => 'Y'],
])->fetchAll();
foreach ($elements as $element) {
    // ...
}

Подробнее рассматривать работу с массивом не буду. Массив всегда можно вывести и посмотреть содержимое. А вот с объектами посложнее, ниже буду рассматривать работу как с объектом. Заменив fetchCollection на fetchAll, а fetchObject на fetchRow можно получить массив полей элемента и вывести то, что получилось. Для удобства именования можно использовать алиасы в select.

Работа с элементом как с объектом

Есть возможность работать с элементами инфоблока как с объектами. Для этого используем методы fetchObject для получения объекта (один элемент) и fetchCollection для получения коллекции объектов (выборка).

Пример для одного элемента:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getByPrimary($elementId, array(
    'select' => array('ID', 'NAME', 'DETAIL_PICTURE')
))->fetchObject();

var_dump($element->getId());
// int(6)
var_dump($element->getName());
// string(42) "Штаны Цветочная Поляна"
var_dump($element->getDetailPicture());
// int(48)

Пример для нескольких элементов:

$elements = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'NAME', 'DETAIL_PICTURE'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchCollection();

foreach ($elements as $element) {
    var_dump($element->getName());
    // string(42) "Штаны Цветочная Поляна"
}

Как видим, для получения значений полей используются методы getXyz, например, getName для получения NAME. Используется CamelCase, т.е. для получения например DETAIL_PICTURE используется метод getDetailPicture. Также поля можно получить методом get:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'NAME'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchObject();
var_dump($element->get('NAME'));
// string(46) "Футболка Женская Чистота"

Разделы элементов

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

$elements = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'IBLOCK_SECTION'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchObject();

var_dump ($element->getIblockSection()->getName());
// string(10) "Штаны"

Для получения всех разделов элемента используем поле SECTIONS, так у нас появляется возможность получения коллекции разделов. Получить значения коллекции можно с помощью метода getAll():

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'SECTIONS'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchObject();

foreach ($element->getSections()->getAll() as $section) {
    var_dump($section->getId());
    // int(8)
    var_dump($section->getCode());
    // string(5) "pants"
    var_dump($section->getName());
    // string(10) "Штаны"
}

Свойства элементов

Свойства можно получить методом getXyz, где Xyz - CamelCased-код свойства. У свойств есть VALUE и DESCRIPTION, которые можно получить методами getValue и getDescription соответственно. Для некоторых типов добавляются дополнительные поля для доступа к дополнительной информации (ITEM - значение свойства типа список, ELEMENT - привязанный элемент, SECTION - привязанный раздел, FILE - файл).

Начнем с простого: свойства типа Текст или Число:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getByPrimary($elementId, array(
    'select' => array('ID', 'ARTNUMBER')
))->fetchObject();

var_dump($element->getArtnumber()->getValue());
// string(11) "177-79-00"

Если для свойства включен вывод описания, то его можно получить методом getDescription.

Если свойство множественное, то getSomePropertyCode() вернет коллекцию. Получить значения коллекции также можно с помощью метода getAll(). Рассмотрим на примере множественного свойства типа Справочник:

$elements = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'NAME', 'DETAIL_PICTURE', 'BRAND_REF'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchCollection();

foreach ($elements as $element) {
    foreach ($element->getBrandRef()->getAll() as $value) {
        var_dump($value->getValue());
    }
}
// string(8) "company2"
// string(8) "company3"
// string(6) "brand2"
// string(6) "brand1"
// string(6) "brand3"

Заметили, что получение множественных свойств не создает проблем с дублированием строк, как при одном?

Переходим в свойствам типа Файл. К значениям таких свойств можно привязать информацию из таблицы товаров и получить не только ID файлов, но информацию о файле. Рассмотрим на примере свойства с 2 картинками. Обратите внимание на добавленное к коду свойства слово FILE:

$elements = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'MORE_PHOTO.FILE'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchCollection();

foreach ($elements as $element) {
    foreach ($element->getMorePhoto()->getAll() as $value) {
        var_dump('/upload/' . $value->getFile()->getSubdir().'/'.$value->getFile()->getFileName());
    }
}

//string(55) "/upload/iblock/2d6/2d6d01a93d220c012e40415616a3d0e1.jpg"
//string(55) "/upload/iblock/dd3/dd3495f96990223e3076c97e99b062d9.jpg"

Со свойства типа Список традиционно всё немного сложнее. Получить просто ID значения достаточно просто:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'NEWPRODUCT'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchObject();
var_dump($element->getNewproduct()->getValue());
// int(1)

Если требуется получить ID, XML_ID и значение, то используем ITEM после код свойства, тогда к запросу добавится таблица значений списочных свойств:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'NEWPRODUCT.ITEM'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchObject();
var_dump($element->getNewproduct()->getItem()->getId());
// int(1)
var_dump($element->getNewproduct()->getItem()->getXmlId());
// string(1) "Y"
var_dump($element->getNewproduct()->getItem()->getValue());
// string(4) "да"

У свойств типов Привязка к элементам и Привязка к разделам есть подобное дополнительное поле (ELEMENT/SECTION) для доступа к элементу/разделу:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'RECOMMEND.ELEMENT'],
    'filter' => [
        'ID' => $elementId,
    ],
])->fetchObject();

foreach ($element->getRecommend()->getAll() as $linkElement) {
    var_dump($linkElement->getElement()->getId());
    // int(29)
    var_dump($linkElement->getElement()->getName());
    // string(34) "Платье Красная Фея"
}

Кеширование

Не забываем про возможность кеширование результатов выборок ORM D7:

$element = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
    'select' => ['ID', 'NAME'],
    'filter' => [
        'ID' => $elementId,
    ],
    "cache" => ["ttl" => 3600],
])->fetchObject();


Возврат к списку