问题
I have to serialize an object and I get the ever so common "circular reference error"
I have used the old Symfony method :
$normalizer = new ObjectNormalizer();
// Add Circular reference handler
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getId();
});
$normalizers = array($normalizer);
$encoders = [new JsonEncoder()];
$serializer = new Serializer($normalizers, $encoders);
This work but as of Symfony 4.2 I get the exception you see in the title of this question :
use the "circular_reference_handler" key of the context instead Symfony 4.2
I cannot find any reference to this in the Symfony documentation concerning the Serializer.
https://symfony.com/doc/current/components/serializer.html#handling-circular-references
Does any one know how to use this "key of context" instead of the old method?
回答1:
Unfortunately it is a bit hidden away in the docs, but you can create a class instead of using an anonymous function and then configure the serializer to use this service by default.
It is part of the configuration reference: https://symfony.com/doc/current/reference/configuration/framework.html#reference-serializer-circular-reference-handler
# config/packages/serializer.yaml
serializer:
circular_reference_handler: 'App\Serializer\MyCircularReferenceHandler'
There is no interface specified. Instead the class needs to be invokable. So in your case it could look like this:
class MyCircularReferenceHandler
{
public function __invoke($object)
{
return $object->id;
}
}
回答2:
you can see a reference to this config key here : https://symfony.com/doc/current/reference/configuration/framework.html#circular-reference-handler the doc has not been updated to show usages of this config key
this config key has to be used in one of your config files (framework.yml for instance) to set the service used to handle circular references
serializer:
circular_reference_handler: App\Service\YourCircularReferenceHandler
回答3:
An addendum to @dbrumann's answer, which very nearly worked for me. In my Symfony 4.3 application, the serializer
section of the YAML requires a parent framework
container. So:
# config/packages/serializer.yaml
framework:
serializer:
circular_reference_handler: 'App\Serializer\MyCircularReferenceHandler'
And then in the reference handler:
class MyCircularReferenceHandler {
public function __invoke($object) {
return $object->id;
}
}
To check that the config values are being loaded correctly, you can utilise the Symfony console:
$ php bin/console debug:config framework
If the config values are loaded correctly, you should see them under the appropriate section in the output.
回答4:
Alternatively, you can provide a dynamic handler in context property :
public function normalize($user, $format = null, array $context = [])
{
// Handle circular references
// DEPRECATED in sf 4.2 :
// $this->normalizer->setCircularReferenceHandler(function ($object) {return $object->getId();});
// Good way in sf > 4.2
$context['circular_reference_handler'] = function ($object) {return $object->getId();};
// Return data
$data = $this->normalizer->normalize($user, $format, $context);
}
回答5:
In messenger configuration, You can call an object method like this:
class CircularReferenceHandler
{
public function handle($object, string $format, array $context)
{
return $object->getId();
}
}
# config/package/messenger.yaml
framework:
messenger:
serializer:
default_serializer: messenger.transport.symfony_serializer
symfony_serializer:
format: json
context: {circular_reference_handler: 'App\application\Helpers\CircularReferenceHandler::handle'}
来源:https://stackoverflow.com/questions/54645363/use-the-circular-reference-handler-key-of-the-context-instead-symfony-4-2