While working with mapped associations in Doctrine I came upon the problem of serializing proxies. Imagine you have a REST service that returns some objects with an associated collection. E.g. a list of dishes that have a list of ingredients associated.
The problem: serializing proxy objects and their special properties
Doctrine is going to create a proxy class for the mapped ingredients. You can find more information about those proxy objects in the Doctrine documentation. The proxy objects themselves are a great helper when combined with lazy loading. Unfortunately they mess up our REST service because we can not just serialize the object tree we are loading from the database, without adding useless data to the result!
To give you an example, imagine this method in our API controller:
This controller might result in something like that:
As you can see the mapping of Dish->Ingredient works fine, but when we map Dish->Ingredient->IngredientType we get those weird “__initializer__” properties. That is a proxy class. How do we prevent our REST service from throwing that out?
Working on a solution: adding the @Groups annotation to our entites
As you can see in the controller code snippet we are using a serialzer. This one is from the Symfony library. And it actually has some information about excluding properties from serializing. The recommended way is using the
@Groups annotation. Check out the Symfony documentation for more information about the
We start by adding the annotation to our entities:
Add the annotation to the referenced entities properties too!
You can of cause add more groups, for example in cases were you’d like to serve only parts of your entities. E.g. a slim list of dishes without ingredients. I skip the
Groups annotation for the id property of all subelements like ingredient, because I do not have a use case were I’d like to retrieve just one ingredient.
Working on a solution: Using a newly configured serializer
Ok so far we did the following:
- Use the Symfony serializer to serialize our data for the REST service
- Add the
@Groupsannotation to all fields in all required entities
Now we have to tell the serializer about our groups!
Before we start: I always declare my controller as a service! Therefore I rely on dependency injection. This solution might look different if you extend Symfony’s
The standard Serializer that is injected by Symfony is already configured to use the
@Groups annotation. This is part of my
services.yml in case you need it:
Using the serializer with groups is easy:
This is it! Just add some annotations, tell the serializer about it and you are good to go.