例如,我有两个实体:main(父)实体(例如User
)和依赖实体(Post
)。我想使用JMS Serializer序列化User
实体以及其第一个发布日期的附加信息。存储在DB中的发布日期是timestamp int,但是我想用我的帮助程序(只是一个服务)将它序列化,它将int转换为带有某种格式的sting。
尝试在实体类中使用方法创建virtual_property
,但未能将我的帮助器注入实体类。解决它的唯一方法是将自己序列化为控制器:
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;
}
注意:这个例子是合成的,在现实世界中我有更复杂的方法,而不仅仅是日期格式化程序。但主要观点是一样的。
我觉得应该有更好的方法来做到这一点。
答案 0 :(得分:3)
Dmtry的解决方案应该适合您的情况。
在这种情况下,事件监听器/订户是最佳解决方案。
更通用的解决方案,即使对象也能工作,并且会触发JMS序列化程序的整个事件系统部分(Dmtry的解决方案仅适用于基元,仅适用于JSON / YAML,而不是XML),是:
class MyFormatter implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.post_serialize',
'method' => 'onPostSerialize',
'class' => 'YourEntity'
),
);
}
public function __construct(MyFormatter $foermatter)
{
$this->formatter = $formatter;
}
public function onPostSerialize(ObjectEvent $event)
{
$visitor = $event->getVisitor();
$context = $event->getContext();
$timestamp = $event->getObject()->getTimestamp();
$formattedTime = $this->formatter->format($timestamp);
$metadata = new StaticPropertyMetadata('stdClass', 'first_post_date', $formattedTime);
$visitor->visitProperty($metadata, $formattedTime, $context);
}
}
序列化程序忽略 stdClass
...
答案 1 :(得分:1)
当然,还有更好的方法。它被称为序列化事件。
http://jmsyst.com/libs/serializer/master/event_system
您创建活动订阅者
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));
}
P.S。我没有检查代码,所以也许我错了某个方法名称,但想法很明确,我希望