products
.Для работы с элементами инфоблока средствами ORM, необходимо использовать класс \Bitrix\Iblock\Elements\Element_Символьный_код_API_инфоблока_Table, в моём случае это класс \Bitrix\Iblock\Elements\ElementProductsTable. Можно убедиться в этом вызвав следующий код:
//Подключим модуль «Информационные блоки»
\Bitrix\Main\Loader::includeModule('iblock');
//Имя ORM класса для работы с инфоблоком «Одежда»
echo \Bitrix\Iblock\Iblock::wakeUp(IBLOCK_CATALOG_ID)->getEntityDataClass(); //Где IBLOCK_CATALOG_ID - содержит ID инфоблока «Одежда»
Выведет строку \Bitrix\Iblock\Elements\ElementProductsTable. Давайте рассмотрим практические примеры работы, подберём аналоги уже привычных нам методов старого ядра.
Аналог CIBlockElement::GetById() в ORM
Для получения данных по элементу инфоблока, по ID этого элемента, используется метод getByPrimary()
вашего «виртуального класса»:
$product = \Bitrix\Iblock\Elements\ElementProductsTable::getByPrimary(10, [ //10 - ID товара, «Платье, Красная фея»
'select' => ['ID', 'NAME', 'PREVIEW_TEXT', 'DETAIL_PICTURE', 'MANUFACTURER', 'MATERIAL'],
])->fetch();
В переменной $product
будет примерно такая информация:
Содержимое переменной: Array
(
[ID] => 10
[NAME] => Платье Красная Фея
[PREVIEW_TEXT] =>
[DETAIL_PICTURE] => 68
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MANUFACTURER_ID] => 2148
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MANUFACTURER_IBLOCK_ELEMENT_ID] => 10
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MANUFACTURER_IBLOCK_PROPERTY_ID] => 10
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MANUFACTURER_VALUE] => Россия "Модница"
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MATERIAL_ID] => 2156
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MATERIAL_IBLOCK_ELEMENT_ID] => 10
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MATERIAL_IBLOCK_PROPERTY_ID] => 11
[IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MATERIAL_VALUE] => трикотаж
)
Обратите внимание, что ключи пользовательских свойств инфоблока, MANUFACTURER
и MATERIAL
указываются как есть, без префикса PROPERTY_
. Чтобы избежать таких длинных ключей как IBLOCK_ELEMENTS_ELEMENT_PRODUCTS_MANUFACTURER_IBLOCK_ELEMENT_ID
в результирующем массиве, можно использовать псевдонимы, вот так:
$product = \Bitrix\Iblock\Elements\ElementProductsTable::getByPrimary(10, [ //10 - ID товара, «Платье, Красная фея»
'select' => ['ID', 'NAME', 'PREVIEW_TEXT', 'DETAIL_PICTURE', 'MANUFACTURER_' => 'MANUFACTURER', 'MATERIAL_'=>'MATERIAL'],
])->fetch();
В таком случае, данные приходят в более удобном виде:
Содержимое переменной: Array
(
[ID] => 10
[NAME] => Платье Красная Фея
[PREVIEW_TEXT] =>
[DETAIL_PICTURE] => 68
[MANUFACTURER_ID] => 2148
[MANUFACTURER_IBLOCK_ELEMENT_ID] => 10
[MANUFACTURER_IBLOCK_PROPERTY_ID] => 10
[MANUFACTURER_VALUE] => Россия "Модница"
[MATERIAL_ID] => 2156
[MATERIAL_IBLOCK_ELEMENT_ID] => 10
[MATERIAL_IBLOCK_PROPERTY_ID] => 11
[MATERIAL_VALUE] => трикотаж
)
Элемент инфоблока как объект
С данными элемента инфоблока можно работать не только как с массивом, но и как с объектом. Для этого используйте метод fetchObject()
вместо fetch()
после вызова getByPrimary()
.
$product = \Bitrix\Iblock\Elements\ElementProductsTable::getByPrimary(10, [ //10 - ID товара, «Платье, Красная фея»
'select' => ['ID', 'NAME', 'PREVIEW_TEXT', 'DETAIL_PICTURE', 'MANUFACTURER_' => 'MANUFACTURER', 'MATERIAL_'=>'MATERIAL'],
])->fetchObject();
В данном случае, в $product
будет получен объект класса Bitrix\Iblock\Elements\EO_ElementProducts с множеством методов для работы с ним. Например:
//Получить id товара
echo $product->getId(); //10
//Получить наименование товара
echo $product->getName(); //"Платье Красная Фея"
//Получить id детального изображения
echo $product->getDetailPicture(); //68
Как видите для получения значений элемента инфоблока используются так называемые геттеры (методы getXXXX где XXX — название поля в «верблюжьей нотации» или CamelCase). Существует так же общий метод get()
который принимает наименование поля, значение которого вам нужно получить. Например:
//Получим id элемента
echo $product->Get('ID'); // 10
//Получим наименование элемента
echo $product->Get('NAME'); // "Платье Красная фея"
Свойства элемента
Свойства элементов (когда мы работаем с ними в виде объекта) так же получаются при помощи геттеров (методов getXXXX где XXXX — код свойства записанный как CamelCase). У каждого свойства есть поле значения VALUE
и описания DESCRIPTION
и соответcnвующие методы для доступа к ним getValue()
и getDescription()
. Рассмотрим пример:
//Получим данные товара
$product = \Bitrix\Iblock\Elements\ElementProductsTable::getByPrimary(10, [ //10 - ID товара, «Платье, Красная фея»
'select' => ['ID', 'NAME', 'PREVIEW_TEXT', 'DETAIL_PICTURE', 'MANUFACTURER', 'MATERIAL'], //MANUFACTURER и MATERIAL свойства типа «Строка»
])->fetchObject();
//Получим значение свойства MANUFACTURER
var_dump($product->getManufacturer()->getValue());
В результате получим строку:
string(29) "Россия "Модница""
Чтобы получить дополнительную информацию для некоторых типов свойств через ORM, нужно указать дополнительный ключ при выборке свойства:
- FILE — свойство типа файл
- ITEM — свойство типа список,
- ELEMENT — свойство типа привязка к элементу инфоблока
- SECTION — свойство типа привязка к разделу инфоблока
Давайте рассмотрим это детальнее. У нашего элемента есть следующие свойства требуемых типов:
- MORE_PHOTO — Картинки галереи (тип файл)
- NEWPRODUCT — Новинка (тип список)
- RECOMMEND — С этим товаром рекомендуем (тип привязка к элементу)
- NEWS_SECTION — Показывать в рекламном блоке в новостях (тип привязка к разделу), это я создал для теста, в «коробке» такого нет
Давайте получим их в ORM:
//Получим данные товара
$product = \Bitrix\Iblock\Elements\ElementProductsTable::getByPrimary(10, [
'select' => [
'ID',
'NAME',
'PREVIEW_TEXT',
'DETAIL_PICTURE',
'MORE_PHOTO.FILE', //Обратите внимание на доп.ключи
'NEWPRODUCT.ITEM',
'RECOMMEND.ELEMENT',
'NEWS_SECTION.SECTION'
],
])->fetchObject();
Свойство типа файл в ORM
Рассмотрим следующий код:
//Выведем доп.фотографии товара
foreach ($product->getMorePhoto()->getAll() as $photo){
echo '<img src="/upload/' . $photo->getFile()->getSubdir() . '/' . $photo->getFile()->getFileName() . '" alt="'. $product->getName() .'" />';
}
Обратите внимание во первых на метод
getAll()
, т.к. свойство MORE_PHOTO — множественное, по сути оно представляет из себя коллекцию значений. Чтобы получить всю коллекцию и применяют метод getAll()
. Далее при обходе элемента коллекции свойства типа файл мы получаем в распоряжение метод getFile()
, который в свою очередь открывает нам доступ к методам getSubdir()
и getFileName()
для получения дополнительной информации о файле.Свойство типа список в ORM
//Свойство типа список
var_dump($product->getNewproduct()->getItem()->getId());
//int(1)
var_dump($product->getNewproduct()->getItem()->getXmlId());
//string(1) "Y"
var_dump($product->getNewproduct()->getItem()->getValue());
//string(4) "да"
Как видите для свойств типа список (при использовании специального ключа .ITEM) добавляется метод getItem()
который позволяет получить ID значения списка методом getId()
, внешний код значения getXmlId()
и само значение методом getValue()
.Свойство типа привязка к элементам инфоблока в ORM
//Получим привязанные элементы
foreach ($product->getRecommend()->getAll() as $recommendedProduct){
echo 'Рекомендуемый товар ID -' . $recommendedProduct->getElement()->getId() . ' наименование - ' . $recommendedProduct->getElement()->getName() . '<br/>';
}
Т.е. рекомендуемые товары так же являются множественным свойством получаем коллекцию значений через getAll()
. Далее мы видим, что элементу коллекции доступен метод getElement()
через который мы можем узнать некоторую информацию об элементе, например ID getId()
и наименование getName()
.
Свойство типа привязка к разделу инфоблока в ORM
//Получим id привязанного раздела
var_dump($product->getNewsSection()->getSection()->getId());
//Получим наименование привязанного раздела
var_dump($product->getNewsSection()->getSection()->getName());
Как и в случае с предыдущим типом свойств нам доступен метод getSection() через который мы можем узнать некоторую дополнительную информацию о связанном с элементом разделе другого инфоблока.
Аналог CIBlockElement::GetList() в ORM
В качестве аналога к всем полюбившимся методу CIBlockElement::GetList()
используется getList()
из D7 который применялся к HL-блокам ранее. Приведу пример:
$products = \Bitrix\Iblock\Elements\ElementProductsTable::getList([
'select' => ['ID', 'NAME', 'PREVIEW_TEXT', 'DETAIL_PICTURE', 'MANUFACTURER_' => 'MANUFACTURER', 'MATERIAL_'=>'MATERIAL'],
'filter' => ['=ACTIVE' => 'Y'],
])->fetchAll();
foreach ($products as $product) {
//...что-то делаем с данными продуктов...
}
Тут всё как в HL блоках D7, поэтому детально разбирать этот вопрос я не стану.
Кеширование результата выборки данных
В Битрикс ORM несколько упростили процедуру кеширования результатов выборки из инфоблока. Для этого вам достаточно добавить в массив параметра метода getList()
поле cache и указать параметры кеширования:
$product = \Bitrix\Iblock\Elements\ElementCatalogTable::getList([
'select' => [
'ID',
'NAME',
'PREVIEW_TEXT',
'DETAIL_PICTURE'
],
'filter' => [
'ID' => 10,
],
'cache' => [
'ttl' => 3600
],
])->fetchObject();
В одной из ближайших статей я напишу простой компонент в двух версиях, старой с использованием классических приёмов работы с ифноблокми и новой с использованием ORM и сравню производительность.
Надеюсь статья окажется для вас полезной, желаю удачи!
Спасибо, описали гораздо проще и лучше, чем на офф сайте битрикса) Подскажите, а как через D7 сохранять значения в свойства элемента? Допустим есть форма на сайте. Мы сохраняем в ИБ заявки на услуги по api. Как передать значения в свойства элемента на D7 и ORM?
$element->setPropertyName($value);//свойство типа строка $element->addToPropertyName($value);//множественное свойство типа строка $element->save();