Is there any way to set the circular reference limit in the serializer component of Symfony (not JMSSerializer) with any config or something like that?
I have a REST Application with FOSRestBundle and some Entities that contain other entities which should be serialized too. But I'm running into circular reference errors.
I know how to set it like this:
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer();
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getName();
});
But this has to be done in more than one controller (overhead for me). I want to set it globally in the config (.yml) e.g. like this:
framework:
serializer:
enabled: true
circular_limit: 5
Found no serializer API reference for this so I wonder is it possible or not?
The only way I've found is to create your own object normalizer to add the circular reference handler.
A minimal working one can be:
Then declare as a service with a slithly higher priority than the default one (which is -1000):
This normalizer will be used by default everywhere in your project.
For a week have I been reading Symfony source and trying some tricks to get it work (on my project and without installing a third party bundle: not for that functionality) and I finally got one. I used CompilerPass (https://symfony.com/doc/current/service_container/compiler_passes.html)... Which works in three steps:
1. Define
build
method in bundleI choosed
AppBundle
because it is my first bundle to load inapp/AppKernel.php
.src/AppBundle/AppBundle.php
2. Write your custom
CompilerPass
Symfony serializers are all under the
serializer
service. So I just fetched it and added to it aconfigurator
option, in order to catch its instanciation.src/AppBundle/AppCompilerPass.php
3. Write your configurer...
Here, you create a class following what you wrote in the custom CompilerPass (I choosed
AppConfigurer
)... A class with an instance method named after what you choosed in the custom compiler pass (I choosedconfigureNormalizer
).The symfony serializer contains normalizers and decoders and such things as private/protected properties. That is why I used PHP's
\Closure::bind
method to scope the symfony serializer as$this
into my lambda-like function (PHP Closure).Then a loop through the nomalizers (
$this->normalizers
) help customize their behaviours. Actually, not all of those nomalizers need circular reference handlers (likeDateTimeNormalizer
): the reason of the condition there.src/AppBundle/AppConfigurer.php
Conclusion
As said earlier, I did it for my project since I dind't wanted FOSRestBundle nor any third party bundle as I've seen over Internet as a solution: not for that part (may be for security). My controllers now stand as...