我有这个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 Serializer在序列化时选择了这个动态属性。我尝试在JMS序列化程序上创建onPostSerialize
事件订阅者,但是没有明确的方法来检查这是GET ONE
还是GET COLLECTION
请求。我不需要GET COLLECTION
上的这种行为,也会导致收集序列化的巨大性能损失。此外,我不想创建任何具有permission
属性的基本实体类。
也许还有其他方法来处理这种情况?
答案 0 :(得分:-1)
我能想象的是虚拟财产和序列化组合的组合:
向您的实体添加属性,如:
/**
* @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);