Je dois sérialiser un objet et j'obtiens la très courante "erreur de référence circulaire"
J'ai utilisé l'ancienne méthode Symfony:
$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);
Cela fonctionne mais à partir de Symfony 4.2, j'obtiens l'exception que vous voyez dans le titre de cette question:
utilisez la clé "circular_reference_handler" du contexte à la place de Symfony 4.2
Je ne trouve aucune référence à cela dans la documentation Symfony concernant le sérialiseur.
https://symfony.com /doc/current/components/serializer.html#handling-circular-references
Est-ce que quelqu'un sait utiliser cette "clé de contexte" au lieu de l'ancienne méthode?
5 Réponses :
vous pouvez voir une référence à cette clé de configuration ici: https://symfony.com/doc/current/reference/configuration/framework.html#circular-reference-handler le document n'a pas été mis à jour pour afficher les utilisations de cette clé de configuration
cette clé de configuration doit être utilisé dans l'un de vos fichiers de configuration (framework.yml par exemple) pour définir le service utilisé pour gérer les références circulaires
serializer: circular_reference_handler: App\Service\YourCircularReferenceHandler
Malheureusement, il est un peu caché dans la documentation, mais vous pouvez créer une classe au lieu d'utiliser une fonction anonyme, puis configurer le sérialiseur pour utiliser ce service par défaut.
Cela fait partie de la référence de configuration: https://symfony.com/doc /current/reference/configuration/framework.html#reference-serializer-circular-reference-handler
class MyCircularReferenceHandler { public function __invoke($object) { return $object->id; } }
Aucune interface n'est spécifiée. Au lieu de cela, la classe doit être invocable. Donc, dans votre cas, cela pourrait ressembler à ceci:
# config/packages/serializer.yaml serializer: circular_reference_handler: 'App\Serializer\MyCircularReferenceHandler'
Merci pour la réponse. Mais comment suis-je censé utiliser cette méthode? Je viens de renoncer à tout le $ normalizer-> setCircularReferenceHandler tous ensemble?
@DennisdeBest oui, vous pouvez supprimer setCircularReferenceHandler
. la configuration définit le gestionnaire qui sera automatiquement appelé si une référence circulaire est détectée.
Ok, j'étais un peu confus quant à l'endroit où mettre la clé circular_reference_handler s'avère que c'est dans framework.yaml sous framework: serializer: circular_reference_handler Cette fonction est maintenant appelée correctement. Cela me laisse avec une erreur d'imbrication maximale, mais c'est un tout autre sujet. Merci de votre aide
Vous pouvez également fournir un gestionnaire dynamique dans la propriété context:
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); }
Un addendum à la réponse de @ dbrumann, qui a presque fonctionné pour moi. Dans mon application Symfony 4.3, la section sérialiseur
du YAML nécessite un conteneur framework
parent. Donc:
$ php bin/console debug:config framework
Et puis dans le gestionnaire de référence:
class MyCircularReferenceHandler { public function __invoke($object) { return $object->id; } }
Pour vérifier que les valeurs de configuration sont chargées correctement, vous pouvez utiliser le Console Symfony:
# config/packages/serializer.yaml framework: serializer: circular_reference_handler: 'App\Serializer\MyCircularReferenceHandler'
Si les valeurs de configuration sont chargées correctement, vous devriez les voir dans la section appropriée dans la sortie.
Dans la configuration de Messenger, vous pouvez appeler une méthode objet comme celle-ci:
# 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'}
class CircularReferenceHandler { public function handle($object, string $format, array $context) { return $object->getId(); } }