Краткий пример, практически не особо полезный, но для иллюстрации достаточно простой:
Видно, что b_iblock_section_element цепляется к b_iblock_section, а вот b_iblock_element цепляется уже к b_iblock_section_element. И таких ссылающихся друг на друга таблиц в запросе может быть много. Только вот проблема: во всех примерах кода, найденных в интернете, в JOIN используются только ссылки на таблицы this и ref - то есть, на первоначальную таблицу запроса и на таблицу в текущем registerRuntimeField(). Как ссылаться на таблицы из других "runtime field" - я не нашёл.
Попытка написать аналог запроса на D7 ORM:
В коде есть закомментированная строка - это первоначальная попытка сделать JOIN по наитию - не работает, пишет
Под закомментированной строкой - строка с работоспособным вариантом. Но он больше похож на кулхацкерский, чем на какой-либо штатный, т.к. использует скрытую логику генерации алиасов таблиц, типа iblock_section_se. Если в будущем авторы ORM решат использовать другую логику - то запрос отвалится.
Рабочий сгенерированный запрос выглядит так:
На безрыбье и рак рыба - но можно ли такое написать поприличней?
| Код |
|---|
SEL ECT e.NAME FR OM b_iblock_section s INNER JOIN b_iblock_section_element se on se.IBLOCK_SECTION_ID = s.ID INNER JOIN b_iblock_element e on e.ID = se.IBLOCK_ELEMENT_ID WHERE s.ID = 954 LIMIT 1 |
Видно, что b_iblock_section_element цепляется к b_iblock_section, а вот b_iblock_element цепляется уже к b_iblock_section_element. И таких ссылающихся друг на друга таблиц в запросе может быть много. Только вот проблема: во всех примерах кода, найденных в интернете, в JOIN используются только ссылки на таблицы this и ref - то есть, на первоначальную таблицу запроса и на таблицу в текущем registerRuntimeField(). Как ссылаться на таблицы из других "runtime field" - я не нашёл.
Попытка написать аналог запроса на D7 ORM:
| Код |
|---|
use Bitrix\Main\DB\SqlExpression;
use Bitrix\Iblock\{SectionTable, SectionElementTable, ElementTable};
$q = SectionTable::query()
->registerRuntimeField('se', [
'data_type' => SectionElementTable::class,
'reference' => ['=ref.IBLOCK_SECTION_ID' => 'this.ID'],
'join_type' => "INNER",
])
->registerRuntimeField('e', [
'data_type' => ElementTable::class,
//'reference' => ['=ref.ID' => 'se.IBLOCK_ELEMENT_ID'],
'reference' => ['=ref.ID' => new SqlEx * pression('?#','iblock_section_se.IBLOCK_ELEMENT_ID')],
'join_type' => "INNER",
])
->setSelect(['e.NAME'])
->setFilter(['ID' => 954])
->setLimit(1)
->getQuery()
;
echo "$q\n"; |
В коде есть закомментированная строка - это первоначальная попытка сделать JOIN по наитию - не работает, пишет
| Цитата |
|---|
| Unknown reference value `se.IBLOCK_ELEMENT_ID` |
Под закомментированной строкой - строка с работоспособным вариантом. Но он больше похож на кулхацкерский, чем на какой-либо штатный, т.к. использует скрытую логику генерации алиасов таблиц, типа iblock_section_se. Если в будущем авторы ORM решат использовать другую логику - то запрос отвалится.
Рабочий сгенерированный запрос выглядит так:
| Код |
|---|
SEL ECT `iblock_section_e`.`NAME` AS `IBLOCK_SECTION_e_NAME` FR OM `b_iblock_section` `iblock_section` INNER JOIN `b_iblock_section_element` `iblock_section_se` ON `iblock_section_se`.`IBLOCK_SECTION_ID` = `iblock_section`.`ID` INNER JOIN `b_iblock_element` `iblock_section_e` ON `iblock_section_e`.`ID` = `iblock_section_se`.`IBLOCK_ELEMENT_ID` WHERE `iblock_section`.`ID` = 954 LIMIT 0, 1 |
На безрыбье и рак рыба - но можно ли такое написать поприличней?