Мне нужно сериализовать объект, и я получаю очень распространенную «ошибку циклической ссылки».
Я использовал старый метод 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);
Эта работа, но с Symfony 4.2 я получаю исключение, которое вы видите в заголовке этого вопроса:
use the "circular_reference_handler" key of the context instead Symfony 4.2
Я не могу найти никаких ссылок на это в документации Symfony, касающейся сериализатора.
https://symfony.com/doc/current/components/serializer.html#handling-circular-references
Кто-нибудь знает, как использовать этот «ключ контекста» вместо старого метода?






вы можете увидеть ссылку на этот ключ конфигурации здесь: https://symfony.com/doc/current/reference/configuration/framework.html#circular-reference-handler документ не был обновлен, чтобы показать использование этого ключа конфигурации
этот ключ конфигурации должен использоваться в одном из ваших файлов конфигурации (например, framework.yml), чтобы установить службу, используемую для обработки циклических ссылок.
serializer:
circular_reference_handler: App\Service\YourCircularReferenceHandler
К сожалению, это немного скрыто в документации, но вы можете создать класс вместо использования анонимной функции, а затем настроить сериализатор для использования этой службы по умолчанию.
Это часть ссылки на конфигурацию: 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'
Интерфейс не указан. Вместо этого класс должен быть вызываемым. Итак, в вашем случае это может выглядеть так:
class MyCircularReferenceHandler
{
public function __invoke($object)
{
return $object->id;
}
}
@DennisdeBest да, вы можете удалить setCircularReferenceHandler. конфиг устанавливает обработчик, который будет автоматически вызываться при обнаружении циклической ссылки.
Хорошо, я немного запутался, куда поместить ключ round_reference_handler, оказывается, он находится в framework.yaml в framework:serializer:circular_reference_handler Теперь эта функция вызывается правильно. Это оставляет мне ошибку максимального вложения, но это совсем другая тема. Спасибо за вашу помощь
Кроме того, вы можете предоставить динамический обработчик в свойстве контекста:
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);
}
Дополнение к ответу @dbrumann, которое почти сработало для меня. В моем приложении Symfony 4.3 для раздела serializer YAML требуется родительский контейнер framework. Так:
# config/packages/serializer.yaml
framework:
serializer:
circular_reference_handler: 'App\Serializer\MyCircularReferenceHandler'
И затем в обработчике ссылок:
class MyCircularReferenceHandler {
public function __invoke($object) {
return $object->id;
}
}
Чтобы убедиться, что значения конфигурации загружаются правильно, вы можете использовать консоль Symfony:
$ php bin/console debug:config framework
Если значения конфигурации загружены правильно, вы должны увидеть их в соответствующем разделе выходных данных.
В конфигурации мессенджера вы можете вызвать метод объекта следующим образом:
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'}
Спасибо за ответ. Однако как я должен использовать этот метод? Я просто отказываюсь от всего $normalizer->setCircularReferenceHandler вместе?