07.07.2019

runtime Отношения в Битрикс ORM D7

ORM D7 в Битрикс появился уже довольно давно. Очень удобно использовать одинаковые методы для запросов к БД с помощью ::getList, просто описывать свои таблицы с помощью ::getMap.
Например вот так можно выбрать информацию о товарах вместе с данными о доступном количестве и зарезервированном количестве + сразу же вывести и название товара.

$products = \Bitrix\Catalog\ProductTable::getList([
    "select" => [
        "PROD_ID" => "ID",
        "NAME" => "IBLOCK_ELEMENT.NAME",
        "IBLOCK_ID" => "IBLOCK_ELEMENT.IBLOCK_ID",
        "TYPE"
    ],
    "filter" => [
        "!TYPE" => \Bitrix\Catalog\ProductTable::TYPE_SKU,
        "IBLOCK_ELEMENT.ACTIVE" => "Y"
    ],
    "order" => [
        "QUANTITY" => "ASC",
        "QUANTITY_RESERVED" => "DESC",
    ]
])->fetchAll();

При использовании старого API: запрос к CCatalogProduct + запрос к CIblockElement мы бы получили вместо одного запроса - два. Да и нужно было бы писать гораздо больше кода для этого. Возможность работы с данными из других таблиц появилась благодаря указанию отношений в методе getMap. Но что делать если по какой то причине эта связь не указана?
В таком случае стоит воспользоваться секцией 'runtime' в массиве параметров метода getList.
Например так:

$dbOrders = \Bitrix\Sale\Internals\OrderTable::getList([
    "select" => [
        "*",
        "PROPERTY_VALUE.*",
    ],
    "filter" => [
        "PROPERTY_VALUE.PROPERTY.CODE" => "LOCATION",
        "!STATUD_ID" != ["C", "RS"]
    ],
    'runtime' => [
        'PROPERTY_VALUE' => [
            'data_type' => \Bitrix\Sale\Internals\OrderPropsValueTable::class,
            'reference' => [
                '=this.ID' => 'ref.ORDER_ID',
            ]
        ],
    ],
    "order" => [
        "ID" => "ASC"
    ]
]);

Данный запрос выведет список заказов в статусах C и RS сразу со значением свойства LOCATION. И все это одним запросом.