1

我有一个Category包含一堆Assets. Category 具有getCount返回其中资产数量的方法。

我使用 FosRestBundle 和 JMSSerializerBundle 将 Category 资产序列化为 json。现在,有一项功能更改引入了不同类型的资产,例如external和资产internal

我仍然想使用实体序列化,我认为通过创建一个PreSerializeEvent我实际上可以做到这一点。

然而,序列化器组件的文档通过将相关部分称为do something

我实际上应该如何在这里做某事?

我想要实现的是更改设置标志时调用的方法。序列化程序的正常情况应该是使用getCount方法,另一方面如果是序列化getExternalCountOnly,则使用 Category 对象上的方法。getCount

这实际上可以在这里做到还是我走错了路?

见我的CategorySerializationSubscriber

<?php
namespace Hn\AssetDbBundle\Listener;

use Hn\AssetDbBundle\Entity\Category;
use Hn\UserBundle\Entity\User;
use JMS\Serializer\Annotation\PostSerialize;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;

/**
 * Class CategorySerializationSubscriber
 * @package Hn\AssetDbBundle\Listener
 */

class CategorySerializationSubscriber implements EventSubscriberInterface
{
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var User $user
     */

    private $user;

    /**
     * @param LoggerInterface $logger
     */

    public function __construct(LoggerInterface $logger, SecurityContextInterface $context)
    {
        $this->user = $context->getToken()->getUser();
        $this->logger = $logger;
        $logger->critical($this->user->getFullNameOrEmail());
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return [
            [
                'event' => 'serializer.pre_serialize',
                'method' => 'onPreSerialize'
            ],
        ];
    }

    /**
     * @param PreSerializeEvent $event
     */

    public function onPreSerialize(PreSerializeEvent $event)
    {
        $category = $this->getCategoryFromEvent($event);

        if (!$category) {
            $this->logger->info('is not a category, aborting');
            return;
        }

        $userCanViewInternalAsset = $this->user->isAllowedToViewInternalAssets();

        /**
         * How to actually do something?
         * 
         * Pseudocode follows:
         */

        if ($userCanViewInternalAsset) {
            $seriaization->replaceMethod($category, 'getCount', 'getExternalAssetCount');
        } else {
            /**
             * $category->getCount(); remains intact
             */
        }
    }

    /**
     * @param PreSerializeEvent $event
     * @return Category|null
     */

    protected function getCategoryFromEvent(PreSerializeEvent $event) {

        /**
         * @var Category $category
         */

        $category = $event->getObject();

        if (!$category instanceof Category) {
            return null;

        }

        return $category;

    }
}
4

1 回答 1

2

如何默认排除,然后使用 postSerialize() 订阅者将其添加到您想要的功能?例如:

在 services.yml 中定义(或services在 config.yml 中):

category_serialization_subscriber:
    class: Hn\AssetDbBundle\Listener\CategorySerializationSubscriber
    tags:
        - { name: jms_serializer.event_subscriber }

然后是以下内容,它是从您上面的类中修改的:

public static function getSubscribedEvents()
{
    return array(array(
        'event'  => 'serializer.post_serialize',
        'class'  => 'Hn\AssetDbBundle\Entity\Category',
        'method' => 'onPostSerialize'
    ));
}

public function onPostSerialize(ObjectEvent $event)
{
    $category = $event->getObject();
    $visitor  = $event->getVisitor();

    if ($this->user->isAllowedToViewInternalAssets()) {
        $visitor->addData('count', $category->getExternalAssetCount());
    } else {
        $visitor->addData('count', $category->getCount());
    }
}
于 2014-12-23T17:34:52.483 回答