Обратный звонок для сериализатора Symfony

Я запускаю Symfony 2.7, и я пытаюсь вывести объект (объект Doctrine) как JSON.

Когда я нормализую объект, я хочу преобразовать некоторые его значения. Для этого я нашел метод setCallbacks в документации, но я не понимаю, как применить его к моему делу.

Есть ли способ вызвать метод setCallbacks в нормализаторе, который задается при вызове службы сериализатора Symfonys?

Вот краткий пример того, чего я пытаюсь достичь:

//ExampleController.php public function getJSONOrderByIdAction($id) { $serializer = $this->get('serializer'); $normalizer = $serializer->getNormalizer(); // <- This is what I'm unable to do $dateTimeToString = function ($dateTime) { return $dateTime instanceof \DateTime ? $dateTime->format(\DateTime::ISO8601) : ''; }; $normalizer->setCallbacks(['time' => $dateTimeToString]); $order = $this->getDoctrine()->find("AppBundle:Order", $id); return new JsonResponse(["order" => $serializer->normalize($order, null, ["groups" => ["public"]])]); } 

Я знаю, что большинство людей переключилось на JMS-сериализатор. Кажется, что встроенный сериализатор должен иметь возможность обрабатывать то, что я пытаюсь достичь.

Служба Serializer по умолчанию создается во время фазы ввода зависимостей, а интерфейс Serializer не позволяет редактировать (полный) поиск нормализаторов.

Я думаю, что у вас есть (по крайней мере) три варианта:

  1. добавьте свой пользовательский нормализатор к сервису Serializer по умолчанию
  2. добавить NormalizableInterface к вашим объектам
  3. создайте новую службу Serializer (или локальный объект, как предложено документами), как вы пытались сделать.

Я думаю, что в вашем сценарии предпочтителен случай 1 (поскольку 2 становится довольно скучным).

Я бы сделал что-то подобное; сначала создайте пользовательский Normalizer

 <?php namespace AppBundle; class DateTimeNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface { /** * {@inheritdoc} */ public function normalize($object, $format = null, array $context = array()) { return $object->format(\DateTime::ISO8601); } /** * {@inheritdoc} */ public function denormalize($data, $class, $format = null, array $context = array()) { return new $class($data); } /** * Checks if the given class is a DateTime. * * @param mixed $data Data to normalize. * @param string $format The format being (de-)serialized from or into. * * @return bool */ public function supportsNormalization($data, $format = null) { return $data instanceof \DateTime; } /** * Checks if the given class is a DateTime. * * @param mixed $data Data to denormalize from. * @param string $type The class to which the data should be denormalized. * @param string $format The format being deserialized from. * * @return bool */ public function supportsDenormalization($data, $type, $format = null) { $class = new \ReflectionClass($type); return $class->isSubclassOf('\DateTime'); } } 

Затем зарегистрируйте его в своих службах:

 # app/config/services.yml services: datetime_normalizer: class: AppBundle\DateTimeNormalizer tags: - { name: serializer.normalizer } 

Мое собственное решение

Следуя совету giosh94mhz, я попытался переключиться на JMS Serializer, но в итоге вернулся к сериализатору Symfonys.

JMS Serializer представил свои собственные проблемы и, ища ответы на эти вопросы, я наткнулся на сообщение в блоге Томаса Джарранда, которое отлично поработало, объясняя, как создавать и внедрять собственные нормализаторы в Symfony.

По-моему, вы, кажется, пытаетесь слишком усложнить ситуацию. Вот такой подход, который я сделал, когда мне нужно было сериализовать мои объекты как JSON:

PHP 2.5 и выше позволяет реализовать метод jsonSerialize для ваших объектов и просто вызвать json_encode непосредственно на вашем объекте.

Если вы все еще используете PHP 2.4, вам просто нужно вручную вызвать jsonSerialize() на ваших объектах.

Например:

 /** * @ORM\Entity */ class MyEntity { ... public function jsonSerialize() { $data = array("foo" => $this->bar()); // add other data here ... return $data } } 

А затем в вызове кода:

 // for PHP 2.5 and up: $normalized = json_encode($myEntityInstance); // for PHP 2.4 and below $normalized = json_encode($myEntityInstance->jsonSerialize());