DEV Community

david duymelinck
david duymelinck

Posted on

New features in Doctrine ORM

While the 3.4.0 version blogpost focuses on property hooks and lazy objects. My eye caught the nested DTO feature

Property hooks

The people that read some of my reinventing Eloquent posts, know I thought of property hooks as a way forward to structure models. And Doctrine actually did it.

The biggest shock for me was that getters and setters were never needed for the models to hydrate. While the documentation on the Doctrine site and Symfony site steer you in that direction.

Lazy objects

This is more an internal change, but a very welcome one thanks to the way PHP is evolving.

Returning a nested DTO

It was already possible to have a nested DTO, but you had to use new for the inner DTO's.

SELECT
  new CmsUserDTO(
     u.name,
     e.email,
     new CmsAddressDTO(
        a.country,
        a.city,
        a.zip
     )
   )
FROM
   Doctrine\Tests\Models\CMS\CmsUser u
JOIN
   u.email e
JOIN
   u.address a
ORDER BY
   u.name
Enter fullscreen mode Exit fullscreen mode

Now you don't need to do that anymore.

SELECT
  new Doctrine\Tests\Models\CMS\CmsUserDTO(
    u.id,
    e.email
    a,
  )
FROM
  Doctrine\Tests\Models\CMS\CmsUser u
LEFT JOIN
  u.email e
LEFT JOIN
  u.address a
ORDER BY
  u.name
Enter fullscreen mode Exit fullscreen mode

For the people who are less familiar with Doctrine this is a DQL query.

Of course this feature is also available with the QueryBuilder.

$query = $entityManager
   ->createQueryBuilder()
   ->select('new '. CmsUserDTO::class .'(u.id, e.email, a)')
   ->from(CmsUser::class, 'u')
   ->leftJoin('u.email', 'e')
   ->leftJoin('u.address', 'a')
   ->orderBy('u.name')
   ->getQuery();
Enter fullscreen mode Exit fullscreen mode

A repository tip, create a DTO interface to type hint the return and a method argument. This allows you to add multiple DTO's without the need to specify each DTO.

Top comments (4)

Collapse
 
jszutkowski profile image
Jarosław Szutkowski

Nice post. If I remember correctly "new DTO" feature was added in Doctrine 2.x. In the third version they improved it so that you can use nested DTOs

Collapse
 
xwero profile image
david duymelinck • Edited

You are right. I have rewritten the post to give more accurate information. Thank you

Do you have any idea why getters and setters are still in the documentation? I even saw a test entity where the property is public and it still has a getter.

Collapse
 
jszutkowski profile image
Jarosław Szutkowski

As you noticed, getters and setters are not required, you can even have private properties without setters because Doctrine hydrates objects with reflection.

In the example you provided there is one setter, setUser, with some logic inside its body, but given that the property is public it doesn't make much sense. This is just a documentation. Its purpose is to show how to use a feature, not necessarily how to structure your code

Thread Thread
 
xwero profile image
david duymelinck

you can even have private properties without setters because Doctrine hydrates objects with reflection

Maybe that is the cause of the behaviour. Keeping the values as protected as possible to avoid that people make mistakes. While we now have readonly classes, property hooks, and asymmetric visibility.