问题描述
我正在尝试序列化作为准则的属性:
I am trying to serialize a property which is a Doctrine Criteria:
public function getUserResults(User $user)
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('user', $user))
;
return $this->getResults()->matching($criteria);
}
我不能使用@VirtualProperty
,因为它需要一个参数,所以我在本文之后为我的一种类型实现了自定义订阅服务器:
I cannot use the @VirtualProperty
because it needs an argument so I implemented a custom subscriber for one of my types following this post:
https://stackoverflow.com/a/44244747
<?php
namespace AppBundle\Serializer;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use JMS\Serializer\EventDispatcher\ObjectEvent;
class ExerciseSubscriber implements EventSubscriberInterface
{
private $currentUser;
public function __construct(TokenStorage $tokenStorage)
{
$this->currentUser = $tokenStorage->getToken()->getUser();
}
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.post_serialize',
'method' => 'onPostSerialize',
'class' => Exercise::class, // if no class, subscribe to every serialization
'format' => 'json', // optional format
),
);
}
public function onPostSerialize(ObjectEvent $event)
{
if (!$this->currentUser) {
return;
}
$exercise = $event->getObject();
$visitor = $event->getVisitor();
$results = $exercise->getUserResults($this->currentUser);
dump($results); // <-- It is an ArrayCollection with many elements
$visitor->setData(
'my_user_results',
$results // <-- when rendered is an empty {}
);
}
}
不幸的是,user_results
属性始终为空!
我查看了序列化程序的源代码,发现:
Unfortunately the user_results
property is always empty!
I looked into the source code for the serializer and I found that:
/**
* Allows you to add additional data to the current object/root element.
* @deprecated use setData instead
* @param string $key
* @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
* It must not contain any objects anymore.
*/
public function addData($key, $value)
{
if (isset($this->data[$key])) {
throw new InvalidArgumentException(sprintf('There is already data for "%s".', $key));
}
$this->data[$key] = $value;
}
请注意它不能再包含任何对象.
我该如何解决?
推荐答案
请尝试使用serializer.post_serialize
事件而不是serializer.pre_serialize
事件.此外,您的虚拟属性名称(user_results)应该与任何现有的可序列化字段都不同.
Please try to use serializer.post_serialize
event instead of serializer.pre_serialize
one. Also your virtual property name (user_results) should be different from any existing serializable fields.
setData方法的第二个参数必须是常规标量或数组.它不能包含任何对象.我建议将JMS序列化器注入到您的侦听器类中,以将对象数组序列化为标量数组.
The second argument of setData method must either be a regular scalar, or an array. It must not contain any objects. I suggest to inject JMS serializer into your listener class to serialize your objects array into array of scalars.
<?php
namespace AppBundle\Serializer;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\Serializer;
class ExerciseSubscriber implements EventSubscriberInterface
{
private $currentUser;
private $serializer;
public function __construct(TokenStorage $tokenStorage, Serializer $serializer)
{
$this->currentUser = $tokenStorage->getToken()->getUser();
$this->serializer = $serializer;
}
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.post_serialize',
'method' => 'onPostSerialize',
'class' => Exercise::class, // if no class, subscribe to every serialization
'format' => 'json', // optional format
),
);
}
public function onPostSerialize(ObjectEvent $event)
{
if (!$this->currentUser) {
return;
}
$exercise = $event->getObject();
$visitor = $event->getVisitor();
$visitor->setData(
'user_results',
$this->serializer->toArray($exercise->getUserResults($this->currentUser))
);
}
}
这篇关于带有参数和自定义侦听器/订阅者的JMS VirtualProperty的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!