1 year ago
#383916
TheodorusMaximus
How to query for an entity that contains an asscociated entity in ArrayCollection field (many-to-many) in Doctrine?
Setup & Problem
There are two entities in my Symfony project (Entries and Persons) that are associated by a many-to-many relationship. An Entry (extended in Interview and LinkedEntry classes) can have one or more authors (ArrayCollection with Person entities) and an author can have written one or more entries (ArrayCollection with Entry entities).
Querying and sorting entries works just fine. But now I am stuck at trying to fetch all entries that are (co-)written by a specific author (Person). Since I want to do some sorting (and later, perhaps, filtering) using DQL, $entries = $person->getEntries();
is not what I am looking for (although it returns the expected results). So I have been trying to write a method in EntryRepository that returns all those entries that have the respective author as element in their authors ArrayCollection. Note that I want to implement the query via the query builder because the ordering and filtering should respect parameters passed on to the method. The problem remains uniformly the same: the repository method returns an empty array although the database clearly says otherwise and $person->getEntries()
returns exactly those entries I am looking for.
I am aware of this being a pretty basic question that -- in one variant or another -- has been asked and answered numerous times here and elsewhere (SymonyCasts, e.g.) and I have studied those answers to the best of my very limited knowledge of Doctrine and DQL but I cannot get it to work on my own for the life of me.
Entites
#[ORM\Entity(repositoryClass: EntryRepository::class)]
#[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorColumn(name: 'entryType', type: 'string')]
#[ORM\DiscriminatorMap(['Entry' => 'Entry', 'Interview' => 'Interview', 'Linked' => 'LinkedEntry'])]
abstract class Entry {
[...]
#[ORM\OrderBy(['lastName' => 'ASC', 'firstName' => 'ASC'])]
#[ORM\ManyToMany(targetEntity: Person::class, inversedBy: 'entries', cascade: ['persist'])]
protected $authors;
[...]
}
#[ORM\Entity(repositoryClass: PersonRepository::class)]
class Person {
[...]
#[ORM\ManyToMany(targetEntity: Entry::class, mappedBy: 'authors')]
private $entries;
[...]
}
What I tried
As already mentioned I tried to incorporate the author criterion into an EntryRepository method that takes care of sorting and filtering. (Note that I omitted those parts here.) Apart from the problem with querying for elements of the ArrayCollection, it works as expected if I delete if ($author !== null) { [...] }
.
class EntryRepository extends ServiceEntityRepository
{
public function findAllSorted(string $subset, string $sortedByField,
string $sortOrder, Person $person): array
{
[...]
$queryBuilder = $this->createQueryBuilder('entry')
->orderBy($field, $order);
[...]
if ($author !== null)
{
$queryBuilder->where(':author MEMBER OF entry.authors')
->setParameter('author', $person);
}
$query = $queryBuilder->getQuery();
return $query->execute();
}
The resulting DQL via dump
looks like this:
"SELECT entry FROM App\Entity\Entry entry
WHERE :author MEMBER OF entry.authors"
The Symphony Profiler logs this query (shortened):
SELECT e0_.id AS id_0, [...] FROM entry e0_ WHERE
(EXISTS (SELECT 1 FROM entry_person e1_ WHERE e1_.entry_id = e0_.id
AND e1_.person_id IN (?))) AND e0_.entryType IN ('Entry', 'Interview', 'Linked')
I made several other attempts at this, working only with person->getId()
instead of the whole entity, trying to join tables and so on -- to no avail. I seem to have a fundamental misconception in my thinking or set-up as neither of them returned something other than an empty array. Any help would be greatly appreciated!
php
symfony
dql
doctrine-query
0 Answers
Your Answer