Используем фильтр CIBlockElement инфоблоков в ORM

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

В данной статье рассматривается практический пример работы с дополнительными таблицами в системе «1С-Битрикс», где используется привязка к элементам инфоблока через их уникальные идентификаторы (ID). Мы покажем, как эффективно применять ORM (Object-Relational Mapping) и фильтры инфоблоков для получения нужных данных.

Тестовый стенд

Для демонстрации примера будем использовать шаблон «Интернет-магазин», входящий в поставку «1С-Битрикс: Управление сайтом» редакции «Малый бизнес» и выше.

Создание дополнительной таблицы

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

use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Fields;

class TestTable extends DataManager
{
    public static function getTableName()
    {
        return 'devbx_test_001';
    }

    public static function getMap()
    {
        return [
            (new Fields\IntegerField('ELEMENT_ID'))->configurePrimary(true),
            (new Fields\TextField('MY_DESCRIPTION')),
        ];
    }
}

Заполнение таблицы тестовыми данными

Теперь заполним нашу таблицу случайными данными. Для этого используем генератор текстов Lorem Ipsum.

$entity = TestTable::getEntity();

//проверяем если таблица не существует, создадим ее
if (!$entity->getConnection()->isTableExists($entity->getDBTableName()))
{
    $entity->createDbTable();

    for ($i=1;$i<20;$i++)
    {
        //возьмем рандомные тексты Lorem ipsum
        $lipsum = \Bitrix\Main\Web\Json::decode(file_get_contents('http://lipsum.com/feed/json'));

        TestTable::add([
            'ELEMENT_ID' => $i,
            'MY_DESCRIPTION' => $lipsum['feed']['lipsum']
        ]);
    }
}

Применение фильтра инфоблоков

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

Формирование фильтра

use Bitrix\Main\DB\SqlExpression;

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

$el = new \CIBlockElement();
$el->prepareSql(
    ['ID'],
    [
        'IBLOCK_ID' => 2,
        '=PROPERTY_MATERIAL' => ['хлопок', 'трикотаж']
    ],
    false,
    [] //убираем сортировку, иначе будет добавлено в SELECT нашего под запроса
);

$subQuery = "SELECT ".$el->sSelect."    FROM ".$el->sFrom." WHERE 1=1 ".$el->sWhere;

Извлечение данных

Используя сформированный подзапрос, получаем данные из нашей таблицы.

$iterator = TestTable::getList([
    'filter' => [
        '@ELEMENT_ID' => new SqlExpression($subQuery),
    ],
    'select' => [
        'ELEMENT_ID',
        'MY_DESCRIPTION'
    ]
]);

while ($row = $iterator->fetch())
{
    print_r($row);
}

Просмотр итогового SQL-запроса

Чтобы увидеть, какой SQL-запрос был сформирован, выполните следующий код:

echo TestTable::query()
    ->setFilter([
        '@ELEMENT_ID' => new SqlExpression($subQuery),
    ])
    ->setSelect([
        'ELEMENT_ID',
        'MY_DESCRIPTION'
    ])->getQuery();

Результатом выполнения данного кода будет такой SQL-запрос:

SELECT 
    `test`.`ELEMENT_ID` AS `ELEMENT_ID`,
    `test`.`MY_DESCRIPTION` AS `MY_DESCRIPTION`
FROM `devbx_test_001` `test` 

WHERE `test`.`ELEMENT_ID` IN (SELECT DISTINCT BE.ID as ID   FROM 
            b_iblock B
            INNER JOIN b_lang L ON B.LID=L.LID
            INNER JOIN b_iblock_element BE ON BE.IBLOCK_ID = B.ID
            INNER JOIN b_iblock_property FP0 ON FP0.IBLOCK_ID = B.ID AND FP0.CODE='MATERIAL'
            INNER JOIN b_iblock_element_property FPV0 ON FPV0.IBLOCK_PROPERTY_ID = FP0.ID AND FPV0.IBLOCK_ELEMENT_ID = BE.ID

            WHERE 1=1 
            AND (

                ((((BE.IBLOCK_ID = 2))))
                AND ((((FPV0.VALUE = 'хлопок')) OR ((FPV0.VALUE = 'трикотаж'))))
            )
            AND (((BE.WF_STATUS_ID=1 AND BE.WF_PARENT_ELEMENT_ID IS NULL))))

Таким образом, мы успешно извлекли необходимые данные из таблицы, используя механизм подзапросов и фильтров в «1С-Битрикс».

Эта статья демонстрирует эффективный способ работы с дополнительными таблицами и фильтрами инфоблоков в «1С-Битрикс».