3

我有这个 REST API。每当请求通过 id (/resource/{id}) 获取资源时,我想permissions在该对象上动态添加一个数组(实体本身没有该字段)。

我想出的是这个事件监听器。它检查控制器返回的结果:

class PermissionFinderListener {
    ...

    public function onKernelView(GetResponseForControllerResultEvent $event)  {
        $object = $event->getControllerResult();

        if (!is_object($object) || !$this->isSupportedClass($object)) {
            return;
        }

        $permissions = $this->permissionFinder->getPermissions($object);
        $object->permissions = $permissions;

        $event->setControllerResult($object);
    }
    ....
}

问题是 JMS 序列化器在序列化时选择了这个动态属性。我尝试onPostSerialize在 JMS 序列化程序上创建事件订阅者,但是没有明确的方法来检查这是否是一个GET ONEGET COLLECTION请求。我不需要这种行为,GET COLLECTION它也会对集合序列化产生巨大的性能影响。此外,我不想创建任何具有permission属性的基实体类。

也许还有其他方法可以处理这种情况?

4

1 回答 1

0

我能想象的是虚拟属性和序列化组的组合:

向您的实体添加一个属性,例如:

 /**
 * @Serializer\VirtualProperty
 * @Serializer\SerializedName("permissions")
 * @Serializer\Groups({"includePermissions"}) */
 *
 * @return string
 */
public function getPermissions()
{
    return $permissionFinder->getPermissions($this);
}

然后,您唯一需要做的就是仅在您的特殊情况下序列化“includePermissions”组(请参阅http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies

如果您无权从您的实体访问 $permissionFinder,您也可以在序列化之前从 Controller/Service 设置实体的权限属性。

编辑

通过包装您的实体并将 VirtualProperty 与 SerializationGroups 一起使用,这是一个更多代码来演示我的意思。这段代码根本没有经过测试——它基本上是我们正在使用的手动复制和剥离的版本。所以请把它当作一个想法!

1)为您的实体创建类似于包装类的东西:

 <?php
 namespace Acquaim\ArcticBundle\Api;

 use JMS\Serializer\Annotation as JMS;

 /**
  * Class MyEntityApi
  *
  * @package My\Package\Api
  */
  class MyEntityApi
{
/**
 * The entity which is wrapped
 *
 * @var MyEntity
 * @JMS\Include()
 */
protected $entity;

protected $permissions;
/**
 * @param MyEntity     $entity
 * @param Permission[] $permissions
 */
public function __construct(
    MyEntity $entity,
    $permissions = null)
{
    $this->entity = $entity;
    $this->permissions = $permissions;
}

/**
 * @Serializer\VirtualProperty
 * @Serializer\SerializedName("permissions")
 * @Serializer\Groups({"includePermissions"})
 *
 * @return string
 */
public function getPermissions()
{
    if ($this->permissions !== null && count($this->permissions) > 0) {
        return $this->permissions;
    } else {
        return null;
    }
}

/**
 * @return object
 */
public function getEntity()
{
    return $this->entity;
}

}

2)在您的控制器中,不要返回您的原始实体,而是获取您的权限并创建具有实体和权限的包装类。设置您的序列化上下文以包含权限并让 ViewHandler 返回您的序列化对象。

如果您没有将序列化上下文设置为 includePermissions,它将被排除在序列化结果之外。

 YourController:

 $myEntity = new Entity();

 $permissions = $this->get('permission_service')->getPermissions();

 $context =   SerializationContext::create()->setGroups(array('includePermissions'));

 $myEntityApi = new MyEntityApi($myEntity,$permissions);

 $view = $this->view($myEntityApi, 200);

 $view->setSerializationContext($context);

 return $this->handleView($view);
于 2015-11-13T14:13:37.407 回答