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
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
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();
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)
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
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.
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 codeMaybe 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.