NEW Operator for DTO construction supporting entities aswell as scalar expressions [orm] - TagMerge

NEW Operator for DTO construction supporting entities aswell as scalar expressions [orm]

AndreRudolphAsked 4 months ago

| Q | A |------------ | ------ | New Feature | yes | RFC | yes/no | BC Break | no

Let's assume I have a scenario where I have a collection and a link entity. A Collection can have multiple links assigned to.

Collection class (minimized example):

class Collection
{
    #[Id]
    #[Column(type: "integer", nullable: false)]
    #[GeneratedValue('AUTO')]
    private ?int $id = null;

    #[OneToMany(mappedBy: 'collection', targetEntity: Link::class, cascade: ['all'])]
    private \Doctrine\Common\Collections\Collection $links;

    // ...
}

and Link class (minimized example):

class Link
{
    #[Id]
    #[Column(type: "integer", nullable: false)]
    #[GeneratedValue('AUTO')]
    private ?int $id = null;

    #[ManyToOne(targetEntity: Collection::class, inversedBy: 'links')]
    private Collection $collection;

}

Let's say I want to retrieve a list of collections with a count of assigned links for each collection. Since I don't want to have an array and instead just one object per row I checked the doctrines documentation and it is possible to create objects from classes that don't need to be an entity itself:

$this->getQueryBuilder()
            ->addSelect('new App\Entity\ViewModels\CollectionLinkCountViewModel(c.id, c.name, c.description, COUNT(links))')
            ->from(Collection::class, 'c')
            ->innerJoin('c.links', 'links')
            ->groupBy('c')
            ->getQuery()
            ->getResult();

According to https://www.doctrine-project.org/projects/doctrine-orm/en/2.9/reference/dql-doctrine-query-language.html#new-operator-syntax it is only possible to pass scalar expressions to a NEW constructor in DQL. I am wondering what the reason was to only allow scalar expressions and not an entity itself?

If I want to have all the informations of the collection entity (name, description, etc.) would have to create possibly a very large and unmaintainable constructor and query string by listing every single column (property) field of c. Wouldn't it be nice to just pass "c" as the collection entity directly into the CollectionLinkCountViewModel constructor? Like this:

$this->getQueryBuilder()
            ->addSelect('new App\Entity\ViewModels\CollectionLinkCountViewModel(c, COUNT(links))')
            ->from(Collection::class, 'c')
            ->innerJoin('c.links', 'links')
            ->groupBy('c')
            ->getQuery()
            ->getResult();

Source: link

Recent Issues

    Programming Languages