2
votes

Utilisez la clé "circular_reference_handler" du contexte à la place symfony 4.2

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?


0 commentaires

5 Réponses :


1
votes

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


0 commentaires

4
votes

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'


3 commentaires

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



0
votes

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);
}


0 commentaires

1
votes

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.


0 commentaires

0
votes

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();
    }
}


0 commentaires