MapEntity attribute: your new Symfony best friend

Thomas BERTRAND
3 min readJul 4, 2023

--

Photo by Hendrik Morkel on Unsplash

Few month ago I wrote an article about the awesome Symfony ParamConverter.
The goal of this ParamConverter is simple: based on the controller route, it automatically finds the element we are looking for, by making the database request and return a 404 error if the element has not been found. It saves a lot of time and reduces the size of the code that makes it easier to read and to maintain.

Thanks to Robin Chalas who commented my previous article and the Symfony blog, I discovered a brand new Symfony EntityValueResolver that comes with its PHP attribute released with Symfony 6.2 as a replacement for the ParamConverter: MapEntity.

How does it work?

Well if you are already familiar with ParamConverter, there is actually, no change regarding to the code 😝
Indeed, most of the time there is actually no specific code to add to use the EntityValueResolver!

Here the resolver tries to get a Product entity from the request attribute available within the Route attribute (here id) exactly like the paramConverter did.

There is anyway one big change for thoses who where using paramConverter: EntityValueResolver and its MapEntity attribute are directly implemented in Symfony whereas paramConverter comes from the external (and deprecated) bundle SensioFrameworkExtraBundle. So using MapEntity instead of paramConverter means that you don’t need the deprecated SensioFrameworkExtraBundle anymore (unless you need other of its features 😊)!

How does it work?

As explained in the above exemple, resolver tries to get an entity from the request param available in the Route attribute (id in the example). It implies the name of the route parameter must be the same in the entity. You will use this “automatic” resolver almost 80% of the time, but for some specific use cases you will have few extra things to do.

How use it with multiple entities?

If the request param is not the same as the entity param or if the route is more complexe (like referring to multiple entities) we need to use the MapEntity attribute.

As we can see with the following example we need to import MapEntity in order to use it, then we call the attribute directly within the function signature.

Here MapEntity will call the find($id) function since we used the “id” param of the MapEntity. Basically we say that the identifier of the entity (in general the $id variable) correspond to the selected route param.

The next example shows how the same result was done with the former paramConverter. Everything was above the function itself and I have to admit that it felt more natural at the first sight, but the MapEntity attribute is much more helpful at the end.

MapEntity with non ID param

In other cases you will need to find an entity by a property that is not the entity identifier. Doing this with MapEntity is quite easy thanks to its mapping parameter that will get a key/value array (route param => entity param).
For example, in the following code we get a product by its slug.

For this usage instead of calling the find($id) method, MapEntity will call the findOneBy() method.

Going further

We saw the most important part of the EntityValueResolver and MapEntity that should already cover the majority of your need in any project. But there are lost of other possibilities and I really recommend you to check the Symfony documentation to know more about this awesome feature!

https://symfony.com/doc/current/doctrine.html#mapentity-options

--

--