Как в битриксе при query join объединить вывод данных?
есть 2 таблицы
Авторы
hl_block1
ID
UF_NAME
Книги
hl_block2
ID
UF_TITLE
UF_AUTHOR_ID
Вопрос:
Как сделать, чтобы в результате была массив 1 автор и у него уже 2 книги в массиве BOOKS?
Делаю join, но каждая книга выводиться отдельно,
Array
(
[0] => Array
(
[ID] => 1
[UF_NAME] => Author Name 1
[AUTHOR_BOOKS_ID] => 1
[AUTHOR_BOOKS_UF_AUTHOR_ID] => 1
[AUTHOR_BOOKS_UF_TITLE] => Book Title 1 from 1
)
[1] => Array
(
[ID] => 1
[UF_NAME] => Author Name 1
[AUTHOR_BOOKS_ID] => 2
[AUTHOR_BOOKS_UF_AUTHOR_ID] => 1
[AUTHOR_BOOKS_UF_TITLE] => Book Title 2 from 1
)
)
use BitrixHighloadblock as HL; use BitrixMainORMFieldsRelationsOneToMany; use BitrixMainORMFieldsRelationsReference; use BitrixMainORMQueryJoin; use BitrixMainORMQueryQuery; CModule::IncludeModule("highloadblock"); const hlblock_author_id = 3; const hlblock_book_id = 4; [$authorsIds, $booksIds] = addData(1, 2); echo '<pre>'; print_r($authorsIds); print_r($booksIds); echo '</pre>'; foreach ($authorsIds as $authorId) { $data = getData($authorId); echo '<pre>'; print_r($data); echo '</pre>'; } function addData($authors=1, $books=1) { for ($a = 1; $a <= $authors; $a++) { $dataAuthor = [ "UF_NAME" => "Author Name $a" ]; $authorId = addEntity(hlblock_author_id, $dataAuthor); $authorsIds[] = $authorId; for ($b = 1; $b <= $books; $b++) { $dataBook = [ "UF_TITLE" => "Book Title $b from $a", "UF_AUTHOR_ID" => $authorId ]; $bookId = addEntity(hlblock_book_id, $dataBook); $booksIds[] = $bookId; } } return [$authorsIds, $booksIds]; } function addEntity($hlblock_id, $data) { $hlblock = HLHighloadBlockTable::getById($hlblock_id)->Fetch(); $entity = HLHighloadBlockTable::compileEntity($hlblock); $entityDataClass = $entity->getDataClass(); $result = $entityDataClass::add($data); return $result->getID(); } function getData($authorId) { if (empty($authorId)) { return false; } $hlblockAuthor = HLHighloadBlockTable::getById(hlblock_author_id)->fetch(); $entityAuthor = HLHighloadBlockTable::compileEntity($hlblockAuthor); $hlblockBook = HLHighloadBlockTable::getById(hlblock_book_id)->fetch(); $entityBook = HLHighloadBlockTable::compileEntity($hlblockBook); $entityBook->addField( (new Reference( 'AUTHOR', $entity, Join::on( 'this.UF_AUTHOR_ID', 'ref.ID' ) ))->configureJoinType(Join::TYPE_LEFT) ); $entityAuthor->addField( (new OneToMany( 'BOOKS', $entityBook, 'AUTHOR')) ); $res = (new Query($entityAuthor)) ->setFilter(['=ID' => $authorId]) ->setGroup(['ID']) ->setSelect(['*','BOOKS']) ->disableDataDoubling() ->exec(); while ($row = $res->fetch()) { $result[] = $row; } return $result; } |
use BitrixHighloadblock as HL; use BitrixMainORMFieldsRelationsOneToMany; use BitrixMainORMFieldsRelationsReference; use BitrixMainORMQueryJoin; use BitrixMainORMQueryQuery; CModule::IncludeModule("highloadblock"); const hlblock_author_id = 3; const hlblock_book_id = 4; [$authorsIds, $booksIds] = addData(1, 2); echo '<pre>'; print_r($authorsIds); print_r($booksIds); echo '</pre>'; foreach ($authorsIds as $authorId) { $data = getData($authorId); echo '<pre>'; print_r($data); echo '</pre>'; } function addData($authors=1, $books=1) { for ($a = 1; $a <= $authors; $a++) { $dataAuthor = [ "UF_NAME" => "Author Name $a" ]; $authorId = addEntity(hlblock_author_id, $dataAuthor); $authorsIds[] = $authorId; for ($b = 1; $b <= $books; $b++) { $dataBook = [ "UF_TITLE" => "Book Title $b from $a", "UF_AUTHOR_ID" => $authorId ]; $bookId = addEntity(hlblock_book_id, $dataBook); $booksIds[] = $bookId; } } return [$authorsIds, $booksIds]; } function addEntity($hlblock_id, $data) { $hlblock = HLHighloadBlockTable::getById($hlblock_id)->Fetch(); $entity = HLHighloadBlockTable::compileEntity($hlblock); $entityDataClass = $entity->getDataClass(); $result = $entityDataClass::add($data); return $result->getID(); } function getData($authorId) { if (empty($authorId)) { return false; } $hlblockAuthor = HLHighloadBlockTable::getById(hlblock_author_id)->fetch(); $entityAuthor = HLHighloadBlockTable::compileEntity($hlblockAuthor); $hlblockBook = HLHighloadBlockTable::getById(hlblock_book_id)->fetch(); $entityBook = HLHighloadBlockTable::compileEntity($hlblockBook); $entityBook->addField( (new Reference( 'AUTHOR', $entity, Join::on( 'this.UF_AUTHOR_ID', 'ref.ID' ) ))->configureJoinType(Join::TYPE_LEFT) ); $entityAuthor->addField( (new OneToMany( 'BOOKS', $entityBook, 'AUTHOR')) ); $res = (new Query($entityAuthor)) ->setFilter(['=ID' => $authorId]) ->setGroup(['ID']) ->setSelect(['*','BOOKS']) ->disableDataDoubling() ->exec(); while ($row = $res->fetch()) { $result[] = $row; } return $result; }
Дополнительно:
Ответы:
НУ наверное сразу не как, только в цикле свернуть уже полученный данные в нужный формат массива.
Вы это можете реализовать только через group by и агрегировать поле BOOKS функцией конкатенацией, разделяя запятыми. А потом просто сделать explode и вы получите свой массив. Других способов я не увидел.
Выборку делать не через fetch() а через getObject()
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для объединения данных при использовании метода query в Битриксе необходимо использовать методы setSelect и setFilter для каждой таблицы, которую вы хотите объединить.
Пример кода для объединения данных из двух таблиц выглядит следующим образом:
use Bitrix\Main\Entity; $query = new Entity\Query(\Bitrix\Iblock\ElementTable::getEntity()); $query->setSelect(array('ID', 'NAME', 'CODE')); $query->setFilter(array('=IBLOCK_ID' => 1)); $subQuery = new Entity\Query(\Bitrix\Iblock\SectionTable::getEntity()); $subQuery->setSelect(array('ID', 'NAME')); $subQuery->setFilter(array('=IBLOCK_ID' => 2)); $query->registerRuntimeField('section', array( 'data_type' => '\Bitrix\Iblock\Section', 'reference' => array('=this.ID' => 'ref.ID'), 'join_type' => 'INNER' )); $query->setSelect(array('section.NAME' => 'SECTION_NAME')); $result = $query->exec(); while ($row = $result->fetch()) { echo $row['ID'] . ' - ' . $row['NAME'] . ' - ' . $row['CODE'] . ' - ' . $row['SECTION_NAME'] . '<br>'; }
В этом примере мы создаем два отдельных запроса для каждой таблицы (элементы и разделы), затем объединяем их с помощью метода registerRuntimeField, указывая соответствие полей для объединения. После этого мы можем получить данные из обеих таблиц в одном запросе и вывести их на страницу.
Надеюсь, это поможет вам объединить данные при использовании метода query в Битриксе. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их!