Symfony 复杂序列化
例如,我有两个实体:主(父)实体(例如Symfony 复杂序列化,symfony,jmsserializerbundle,jms-serializer,Symfony,Jmsserializerbundle,Jms Serializer,例如,我有两个实体:主(父)实体(例如User)和从属实体(Post)。我想使用JMS序列化程序对User实体进行序列化,并提供其第一次发布日期的附加信息。DB中存储的post日期是timestamp int,但我想用我的助手(只是一个服务)将其序列化,该助手将int转换为带有一些格式的sting 尝试在实体类中使用方法创建虚拟属性,但未能将我的助手插入实体类。对我来说,解决这个问题的唯一方法是自己序列化到控制器中: public function someAction() { $ser
User
)和从属实体(Post
)。我想使用JMS序列化程序对User
实体进行序列化,并提供其第一次发布日期的附加信息。DB中存储的post日期是timestamp int,但我想用我的助手(只是一个服务)将其序列化,该助手将int转换为带有一些格式的sting
尝试在实体类中使用方法创建虚拟属性
,但未能将我的助手插入实体类。对我来说,解决这个问题的唯一方法是自己序列化到控制器中:
public function someAction()
{
$serializedUser = $this->serializeEntity($user);
}
public function serializeEntity(User $user)
{
// JMS serialization
$user = $this->get('jms_serializer')->serialize($user, 'array');
if ($user->getPosts()->count()) {
$post = $user->getPosts()->first();
$user['first_post_date'] = $this->get('my_helper_service')->dateFormat($post->getDate());
}
return $user;
}
注意:这个例子是合成的,在现实世界中,我有更复杂的方法,而不仅仅是日期格式化程序。但主要思想是一样的
我觉得应该有更好的方法来做这件事。当然,有更好的方法。这叫做序列化事件 您可以创建事件订阅服务器
my_bundle.serializer_subscriber:
class: MyBundle\Serializer\MyEntitySerializerSubscriber
arguments:
- @bundle.time_formatter
tags:
- { name: jms_serializer.event_subscriber }
然后只需在侦听器中添加所需的数据
public function myOnPostSerializeMethod(ObjectEvent $event)
{
if (!($event->getObject() instance of YourEntity)) {
return;
}
$timestamp = $event->getObject()->getTimestamp();
$visitor = $event->getVisitor();
$visitor->addData('date', $this->formatter->format($timestamp));
}
另外,我没有检查代码,所以可能我在方法的名称上弄错了,但是想法很清楚,我希望有更好的方法。这叫做序列化事件 您可以创建事件订阅服务器
my_bundle.serializer_subscriber:
class: MyBundle\Serializer\MyEntitySerializerSubscriber
arguments:
- @bundle.time_formatter
tags:
- { name: jms_serializer.event_subscriber }
然后只需在侦听器中添加所需的数据
public function myOnPostSerializeMethod(ObjectEvent $event)
{
if (!($event->getObject() instance of YourEntity)) {
return;
}
$timestamp = $event->getObject()->getTimestamp();
$visitor = $event->getVisitor();
$visitor->addData('date', $this->formatter->format($timestamp));
}
另外,我没有检查代码,所以可能我在方法名称方面弄错了,但是想法很清楚,我希望Dmtry的解决方案能够完美地适用于您的情况 在这种情况下,事件侦听器/订阅服务器是最好的解决方案 更通用的解决方案是,它甚至可以处理对象,并将触发JMS序列化程序的整个事件系统部分(Dmtry的解决方案仅适用于原语,仅适用于JSON/YAML,而不适用于XML):
类MyFormatter实现EventSubscriberInterface
{
公共静态函数getSubscribedEvents()
{
返回数组(
排列(
'事件'=>'序列化程序。后序列化',
'方法'=>'onPostSerialize',
“类”=>“您的实体”
),
);
}
公共函数构造(MyFormatter$FoerFormatter)
{
$this->formatter=$formatter;
}
公共函数onPostSerialize(ObjectEvent$event)
{
$visitor=$event->getVisitor();
$context=$event->getContext();
$timestamp=$event->getObject()->getTimestamp();
$formattedTime=$this->formatter->format($timestamp);
$metadata=新的StaticPropertyMetadata('stdClass','first\u post\u date',$formattedTime);
$visitor->visitProperty($metadata、$formattedTime、$context);
}
}
stdClass
被序列化程序忽略…Dmtry的解决方案应该非常适合您的情况
在这种情况下,事件侦听器/订阅服务器是最好的解决方案
更通用的解决方案是,它甚至可以处理对象,并将触发JMS序列化程序的整个事件系统部分(Dmtry的解决方案仅适用于原语,仅适用于JSON/YAML,而不适用于XML):
类MyFormatter实现EventSubscriberInterface
{
公共静态函数getSubscribedEvents()
{
返回数组(
排列(
'事件'=>'序列化程序。后序列化',
'方法'=>'onPostSerialize',
“类”=>“您的实体”
),
);
}
公共函数构造(MyFormatter$FoerFormatter)
{
$this->formatter=$formatter;
}
公共函数onPostSerialize(ObjectEvent$event)
{
$visitor=$event->getVisitor();
$context=$event->getContext();
$timestamp=$event->getObject()->getTimestamp();
$formattedTime=$this->formatter->format($timestamp);
$metadata=新的StaticPropertyMetadata('stdClass','first\u post\u date',$formattedTime);
$visitor->visitProperty($metadata、$formattedTime、$context);
}
}
stdClass
被序列化程序忽略…我考虑了事件,但是这个事件会在每次序列化时触发吗?如果我有几个实体,我想填充它们,那么代码将有很多If($event->getObject()SomeEntity实例){$this->someEntityFormat($event);}
我考虑过事件,但是每次序列化都会触发这个事件吗?如果我有几个要填充的实体,那么代码将有很多If($event->getObject()SomeEntity实例){$this->someEntityFormat($event);}