@askbx

Как в битриксе при 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 Bitrix\Highloadblock as HL;
use Bitrix\Main\ORM\Fields\Relations\OneToMany;
use Bitrix\Main\ORM\Fields\Relations\Reference;
use Bitrix\Main\ORM\Query\Join;
use Bitrix\Main\ORM\Query\Query;

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 = HL\HighloadBlockTable::getById($hlblock_id)->Fetch();
    $entity = HL\HighloadBlockTable::compileEntity($hlblock);
    $entityDataClass = $entity->getDataClass();

    $result = $entityDataClass::add($data);

    return $result->getID();
}

function getData($authorId) {
  if (empty($authorId)) {
    return false;
  }

  $hlblockAuthor = HL\HighloadBlockTable::getById(hlblock_author_id)->fetch();
  $entityAuthor = HL\HighloadBlockTable::compileEntity($hlblockAuthor);

  $hlblockBook = HL\HighloadBlockTable::getById(hlblock_book_id)->fetch();
  $entityBook = HL\HighloadBlockTable::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;
}
  • Вопрос задан
  • 684 просмотра
Пригласить эксперта
Ответы на вопрос 3
НУ наверное сразу не как, только в цикле свернуть уже полученный данные в нужный формат массива.
Ответ написан
Комментировать
@boris4682
Backend developer
Вы это можете реализовать только через group by и агрегировать поле BOOKS функцией конкатенацией, разделяя запятыми. А потом просто сделать explode и вы получите свой массив. Других способов я не увидел.
Ответ написан
Комментировать
AlexeyGfi
@AlexeyGfi
YouTube >>> Битриксоид из Колхоза
Выборку делать не через fetch() а через getObject()
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы