Меню

ORM в инфоблоках, получение информации об элементах инфоблока на D7

Просмотров: 2532

Задача: собрать полные данные об элементах инфоблока, применяя ORM/D7, который пришел на смену устаревшему CIBlockElement::GetList.

Метод CIBlockElement::GetList в позволяет получить практически все данные об элементе: стандартные поля, свойства, цены и другие сведения.

Однако его заменила ORM-методология, где ElementTable::getList не предоставляет готового доступа ко всем данным. Для сбора полной информации, данные нужно подгружать по частям, включая использование классов Bitrix\Iblock\PropertyTable, Bitrix\Iblock\PropertyEnumerationTable и других.

Но, есть способ получить всю нужную информацию, подключив только класс Bitrix\Iblock\Iblock и используя инфоблок как сущность, то есть, фактически превращая его в виртуальный класс.

Видео пример использования ORM D7 в инфоблоках показал в одной из серий видеокурса:
Свой компонент: список объявлений пользователя

Включение ORM в инфоблоках

Для работы с ORM достаточно задать API-идентификатор в настройках инфоблока:

Получение полной информации об элементах инфоблока с использованием ORM

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

use Bitrix\Main\Loader,
       Bitrix\Iblock\Iblock,
       Bitrix\Iblock\SectionTable,
       Bitrix\Catalog\PriceTable;

Loader::includeModule('iblock');

$IBLOCK_ID = 1;

// Инициализация класса инфоблока
$iblockClass = Iblock::wakeUp($IBLOCK_ID)->getEntityDataClass();

$getElements = $iblockClass::getList([
    'select' => [
        // Получаем все поля элемента
        '*',

        // Дополучаем шаблон URL из инфоблока
        'URL' => 'IBLOCK.DETAIL_PAGE_URL',

        // Дополучаем свойство типа строка
        'PREFS_' => 'ATT_PREFS',

        // Дополучаем свойство типа файл
        'PHOTOS_' => 'MORE_PHOTO.FILE',

        // Дополучаем свойство типа список
        'PROCESSOR_' => 'ATT_PROCESSOR.ITEM',

        // Дополучаем свойство типа привязка к элементам
        'RELATED_' => 'ATT_RELATED.ELEMENT',

        // Дополучаем свойство типа привязка к разделам
        'BRANDS_' => 'ATT_RELATED.SECTION',
    ],
])->fetchAll();

foreach ($getElements as $resElement) {

    // Из шаблона ссылки получаем реальный url элемента
    $resElement['URL'] = CIBlock::ReplaceDetailUrl(
        $resElement["URL"],
        $resElement,
        true,
        'E'
    );

    // По ID детальной картинки получаем путь к ней
    $resElement['DETAIL_PICTURE_SRC'] = CFile::GetPath(
        $resElement['DETAIL_PICTURE']
    );

    // Дополучаем цены элемента
    $resElement['PRICES'] = PriceTable::getList([
        'filter' => [
            '=PRODUCT_ID' => $resElement['ID']
        ],
        'select' => [
            '*'
        ]
    ])->fetch();

    // Дополучаем данные о разделе инфоблока в котором элемент
     $resElement['SECTION'] = SectionTable::getList([
        'filter' => [
            'ID' => $resElement['IBLOCK_SECTION_ID']
        ],
        'select' => [
            '*' // Все поля раздела, но можно отобрать только нужные 
        ]
    ])->fetch();

    // Распечатываем полученную информацию
    var_dump($resElement);
}

Метод Iblock::wakeUp получает ORM-класс инфоблока, задав его ID, после чего доступен метод getList.

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

В цикле перебора каждого элемента дополняем информацию: получаем URL элемента, путь к детальной картинке и данные о ценах.

Метод ::getList сгенерированного ORM класса инфоблока, как и в обычных классах D7 принимает параметры:

$res = \Запрос\К нужному классу::getList([
    'order' => // массив- сортировка
    'select' => // массив- выбираемые поля
    'filter' => // массив- фильтр
    'group' =>  // массив- группировка, order должен быть пустой
    'limit' => // число- ограничение выбираемого кол-ва
    'offset' => // число- смещение первого столбца в результате
    'count_total' => // число- дает возможность получить кол-во элементов через метод getCount()
    'runtime' =>  // массив полей сущности, создающихся динамически
    'data_doubling' => // булево (ум. false) - получение одинаковых записей
    'cache' => array( // массив-  кеширование запроса запроса
        'ttl' => 1000,
        'cache_joins' => true
    ),
]);

Получение множественных значений свойств элементов инфоблока через ORM

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

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

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

use Bitrix\Main\Loader;
use Bitrix\Iblock\Iblock;

Loader::includeModule('iblock');

$IBLOCK_ID = 2;
$iblockClass = Iblock::wakeUp($IBLOCK_ID)->getEntityDataClass();

$getElements = $iblockClass::getList([
    'select' => [
        'NAME',
        'ID',
        'BRAND_REF_' => 'BRAND_REF', // Множественное свойство
        'MATERIAL_' => 'MATERIAL',   // Множественное свойство
    ]
]);

$elements = [];
while ($element = $getElements->Fetch()) {
    $id = $element['ID'];

    // Если элемент еще не добавлен в массив, добавляем его
    if (!isset($elements[$id])) {
        $elements[$id] = [
            'NAME' => $element['NAME'],
            'ID' => $id,
            // Подготавливаем ключи для свойств
            'BRAND_REF_VALUE' => [],
            'MATERIAL_VALUE' => []
        ];
        // Здесь можно выполнить дополнительные обработки, из примера выше
    }

    // Добавляем значения множественных свойств только если отсутствуют
    if (
        !empty($element['BRAND_REF_VALUE']) && 
        !in_array($element['BRAND_REF_VALUE'], $elements[$id]['BRAND_REF_VALUE'])
    ) {
        $elements[$id]['BRAND_REF_VALUE'][] = $element['BRAND_REF_VALUE'];
    }
    if (!empty($element['MATERIAL_VALUE']) && 
        !in_array($element['MATERIAL_VALUE'], $elements[$id]['MATERIAL_VALUE'])
    ) {
        $elements[$id]['MATERIAL_VALUE'][] = $element['MATERIAL_VALUE'];
    }
}

foreach ($elements as $element) {
    // Распечатываем полученную информацию
    var_dump($element);
}
  • Создается запрос getList, который выбирает элементы из информационного блока, указав необходимые поля: NAME, ID и два множественных свойства BRAND_REF и MATERIAL.
  • Если элемент еще не добавлен в массив $elements, он добавляется с инициализацией массива для множественных значений.
  • Если множественные значения свойств присутствуют, они добавляются в соответствующие массивы BRAND_REF_VALUE и MATERIAL_VALUE. Добавление происходит без повторов значений.

Почему стоит использовать ORM вместо старого метода CIBlockElement::GetList

Использование ORM для работы с инфоблоками, вместо старого метода CIBlockElement::GetList, имеет ряд значительных преимуществ.

Во-первых, ORM обеспечивает структурированный и читаемый код, что особенно важно в крупных проектах с большим объемом данных и сложной логикой. ORM позволяет работать с объектами и свойствами инфоблока, как с сущностями базы данных, что упрощает манипуляции с данными и делает код более поддерживаемым.

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

Михаил Базаров 01.11.2024
Код
// Примеры различных типов свойств
'PREFS_' => 'ATT_PREFS',    // Строковое свойство
'PHOTOS_' => 'MORE_PHOTO.FILE',    // Свойство-файл
'PROCESSOR_' => 'ATT_PROCESSOR.ITEM',     // Свойство-список
'RELATED_' => 'ATT_RELATED.ELEMENT',    // Привязка к элементам
'BRANDS_' => 'ATT_RELATED.SECTION',     // Привязка к разделам
'MULTIPLE_' => 'ATT_MULTIPLE.VALUE'    // Множественное свойство

Пример использования в видеоуроке
https://bazarow.ru/video/video_new/seazon_2_2024/component-users-bulletins/
Алексей 01.11.2024
Метод Iblock::wakeUp естественно не документирован в Битрикс (((
Михаил Базаров 01.11.2024
Скудно, но все таки в примерах встречается, в новой документации
Кирилл 10.03.2025
Описанный подход имеет два недостатка:
1) если свойство элемента - множественное, то в результирующем массиве данный элемент повторяется столько раз, сколько значений есть у этого свойства. Как этого избежать, не написано.
2) в результирующий массив попадает множество ненужных значений у каждого свойства. Например, для свойства типа "привязка к элементам" получаем значения _ID, _TIMESTAMP_X, _MODIFIED_BY, _DATE_CREATE, _CREATED_BY, _IBLOCK_ID, _IBLOCK_SECTION_ID и все остальные стандартные поля элемента. Если нужно получить только значение свойства типа "привязка к элементам", то в массиве SELECT метода GETLIST нужно указать не ATT_RELATED.ELEMENT, а ATT_RELATED.ELEMENT.NAME. Об этом также не написано.
Михаил Базаров 21.03.2025
Да, со множественными свойствами все сложенее (как и обычно).
Дописал в заметку как быть с ними.
По второму моменту, тут да, нужно работать с тем что есть - больших проблем не должно вызывать

Стоимость и сроки разработки сайтов и приложений

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

Интернет-магазин: индивидуальная разработка от 350 000 руб.
от 5-ти недель

Cоздание интернет-магазина на 1С-Битрикс. Разработка с нуля, оптимизация кода и производительности под конкретный проект и требования. Реализация любого функционала без ограничений готовых решений.

Интернет-магазин: на готовом решении от 60 000 руб.
от 7-ми дней

Готовое решение — вариант для тех, кто не хочет тратить много средств на индивидуальный проект, и не имеет серьезных требований к сайту. Магазин, быстро запускается на базе одного из 200-та готовых решений

Мобильное приложение от 400 000 руб.
от 1-го месяца

Разработка кроссплатформенного мобильного приложения, которое не уступает нативным решениям как в производительности, так и пользовательском опыте. Публикуется в AppStore, GooglePlay и RuStore

Опросник на разработку. После ознакомления, задам уточняющие вопросы и оценю проект по стоимости и срокам разработки.