复杂序列化

Complex serialization

例如,我有两个实体:主(父)实体(例如 User)和从属实体(Post)。我想使用 JMS Serializer 序列化 User 实体及其第一个 post 日期的附加信息。存储在数据库中的 post 日期是时间戳 int,但我想用我的助手(只是一个服务)将它序列化,它将 int 转换为具有某种格式的 sting。

尝试使用实体 class 的方法创建 virtual_property,但未能将我的助手注入实体 class。对我来说解决它的唯一方法是自己序列化到控制器中:

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;
}

注意:这个例子是合成的,在现实世界中我有更复杂的方法,而不仅仅是日期格式化程序。但主要思想是一样的。

我觉得应该有更好的方法来做到这一点。

当然还有更好的办法。它被称为序列化事件。

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。我没有检查代码,所以也许我在某个地方弄错了方法名称,但我希望思路很清楚

Dmtry 的解决方案应该非常适合您的情况。

事件 listener/subscriber 是这种情况下的最佳解决方案。

一个更通用的解决方案,它甚至适用于对象,并将触发 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 被序列化程序忽略...