Doctrine QueryBuilder group, отношение не работает

У меня есть следующий запрос:

$query = $qb->select('p')
->from(get_class($page), 'p')
->innerJoin('p1.translations', 't')
->groupBy('p.id')
->addGroupBy('t.id')
->getQuery();

Доктрина возвращает вышеупомянутое как:

Page entity -> [translation 1, translation 2, translation 3]

Но я хочу результат как:

Page entity 1 -> translation 1
Page entity 1 -> translation 2
Page entity 1 -> translation 3

Кто-нибудь знает, как я могу это сделать? Я хочу вернуть список лиц.

0

Решение

Прежде всего, оба groupBy полностью излишни, предполагая, что оба id поля, по которым вы группируете, являются первичными ключами соответствующих таблиц. Для любого данного (p.id, t.id) комбинация будет иметь не более одного результата, независимо от того, группируете вы или нет.

Во-вторых, даже если вы присоединяетесь к таблице переводов, вы не извлекаете из нее никаких данных (t отсутствует в вашем ->select()). Это так выглядит, поскольку доктрина «волшебным образом» загружает данные в фоновом режиме, когда вы вызываете $page->getTranslations() (при условии, что ваш получатель называется так).

В-третьих, ваша проблема не с groupBy, Вы совершенно не понимаете, что на самом деле делает ORM при гидратации результата запроса. SQL-запрос, который доктрина генерирует из вашего кода будут на самом деле возвращайте результаты так, как вы ожидаете, с «Page entity 1», повторенным несколько раз.

Однако сейчас наступает этап увлажнения. Doctrine читает первую строку результатов, строит сущность «Страница 1» и сущность «Перевод 1», связывает их и добавляет их в свой внутренний реестр сущностей. Затем, для второго результата, Doctrine замечает, что она уже увлажнила объект «Page entity 1» и (это важная часть!) повторно использует один и тот же объект из первого ряда, добавив второй перевод к ->translation Коллекция существующего объекта. Даже если вы снова прочитаете «Страница сущности 1» в совершенно другом запросе вашего кода, вы все равно снова получите тот же объект PHP.

Такое поведение лежит в основе того, что делает Доктрина. По сути, любая строка таблицы в базе данных всегда будет отражаться одним объектом на стороне PHP, независимо от того, как часто или каким образом вы фактически читаете ее из базы данных.

Подводя итог, ваш запрос должен выглядеть следующим образом:

$query = $qb->select('p, t')
->from(get_class($page), 'p')
->innerJoin('p.translations', 't')
->getQuery();

Если вам действительно нужно перебрать все (p, t) комбинации, сделайте это с помощью вложенных циклов:

foreach ($query->getResult() as $p) {
foreach ($p->getTranslations() as $t) {
// do something
}
}

РЕДАКТИРОВАТЬ: Если ваши отношения являются двунаправленными, вы также можете изменить свой запрос:

$query = $qb->select('t, p')
->from('My\Bundle\Entity\Translation', 't')
->innerJoin('t.page', 'p')
->getQuery();

Теперь в вашем примере вы на самом деле получаете 3 результата, которые вы можете перебрать в одном foreach (). Вы бы все равно получили только один объект «Page entity 1», со всеми переводами в результате запроса, указывающими на него.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector