Doctrine - извлекает коллекцию из отношения «многие ко многим» без корневого объекта - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть 2 сущности, скажем

class A
{
...
    /**
     * @var ArrayCollection
     *
     * @ORM\ManyToMany(targetEntity="B")
     * @ORM\JoinTable(name="a_b",
     *      joinColumns={@ORM\JoinColumn(name="a_id", referencedColumnName="id", onDelete="CASCADE")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="b_id", referencedColumnName="id", onDelete="CASCADE")}
     * )
     */
    protected $bs;
...
    /**
     * @return ArrayCollection
     */
    function getBs()
    {
        return $this->bs;
    }
...
}

и

class B
{
...
}

с отношением "многие ко многим", определенным только на одной стороне (A).

Чего я хотел бы добиться, так это получить коллекцию объектов B, связанных с одним произвольным объектом A, с помощью построителя запросов Doctrine. Я ограничен в том, чтобы делать это только с помощью построителя запросов, что-то вроде $a->getBs() не вариант. То же самое с нативным sql, определяющим отношения с обеих сторон или использующим репозитории, не может быть и речи.

Ожидаемый результат должен выглядеть примерно так:

[
    B {},
    B {},
]

Я предположил что-то вроде

$em = $container->get('doctrine');
$qb = $em->createQueryBuilder();

$qb->select('b')
    ->from(A::class, 'a')
    ->join('a.bs', 'b')
    ->where($qb->expr()->eq('a', ':entity'))
    ->setParameters(['entity' => 1]);

$res = $qb->getQuery()->getResult();

будет работать.

Увы, выдает ошибку Cannot select entity through identification variables without choosing at least one root entity alias.

пробовал что-то вроде $qb->select('a.bs') но тот тоже выдает ошибку Invalid PathExpression. Must be a StateFieldPathExpression.

У меня есть решение для этого (см. Ниже), но оно действительно ужасно, поэтому я надеюсь, что у кого-то есть лучшее.

$qb->select('b')
    ->from(A::class, 'a')
    ->join('a.bs', 'ab')
    ->join(B::class, 'b', Join::WITH, $qb->expr()->eq('ab.id', 'b.id'))

Буду признателен, если кто-нибудь сможет дать совет.

1 Ответ

0 голосов
/ 07 ноября 2018

В этом случае корневым объектом является A - он должен быть в методе выбора. Вы можете попробовать что-то вроде этого:

$qb = $em->createQueryBuilder();

$qb->select('a, bs')
    ->from(A::class, 'a')
    ->leftJoin('a.bs', 'bs')
    ->where('a.id = :id')
    ->setParameter('id', 1)
;

$entityA = $qb->getQuery()->getOneOrNullResult();
$entityA->getBs(); // Returns all bs from entity A with id 1
...