Symfony 在要序列化的实体上添加动态属性

Symfony 在要序列化的实体上添加动态属性,symfony,jms-serializer,Symfony,Jms Serializer,我有这个RESTAPI。每当请求通过id(/resource/{id})获取资源时,我都希望动态地在该对象上添加权限数组(实体本身没有该字段) 我想到的是这个事件监听器。它检查控制器返回的结果: class PermissionFinderListener { ... public function onKernelView(GetResponseForControllerResultEvent $event) { $object = $event->g

我有这个RESTAPI。每当请求通过id(/resource/{id})获取资源时,我都希望动态地在该对象上添加
权限
数组(实体本身没有该字段)

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

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序列化程序在序列化时选择了这个动态属性。我尝试在JMS序列化程序上创建
onPostSerialize
事件订阅服务器,但是没有明确的方法来检查这是
GET ONE
还是
GET COLLECTION
请求。我不需要在
GET COLLECTION
上使用这种行为,而且它会对集合序列化产生巨大的性能影响。另外,我不想创建任何具有
权限
属性的基本实体类


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

我可以想象虚拟财产和序列化组的组合:

向实体添加属性,如:

 /**
 * @Serializer\VirtualProperty
 * @Serializer\SerializedName("permissions")
 * @Serializer\Groups({"includePermissions"}) */
 *
 * @return string
 */
public function getPermissions()
{
    return $permissionFinder->getPermissions($this);
}
然后,您只需要在特殊情况下序列化“includePermissions”组(请参阅)

如果您没有从实体访问$permissionFinder的权限,您还可以在序列化实体之前从控制器/服务设置实体的权限属性

编辑

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

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

}

我希望ro避免更改或耦合我的实体,那么将您的实体包装成一个具有虚拟财产的实体怎么样?e、 g.通过扩展ViewHandler或类似的东西?那么你就不需要使用事件监听器了。也许你可以用一些代码来说明你是什么样的人suggesting@nn4n4s:已添加示例,请检查
 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);