Php FOSRestBundle:请求中请求的属性函数中的部分响应 上下文
我发现了很多关于FOSRest的部分API响应的问题,所有答案都基于JMS序列化程序选项(排除、包含、组等)。它工作得很好,但我试图实现一些不太“静态”的东西 假设我有一个具有以下属性的用户:Php FOSRestBundle:请求中请求的属性函数中的部分响应 上下文,php,api,symfony,fosrestbundle,jmsserializerbundle,Php,Api,Symfony,Fosrestbundle,Jmsserializerbundle,我发现了很多关于FOSRest的部分API响应的问题,所有答案都基于JMS序列化程序选项(排除、包含、组等)。它工作得很好,但我试图实现一些不太“静态”的东西 假设我有一个具有以下属性的用户:idusernamefirstnamelastname年龄性别 我使用端点GET/users/{id}和以下方法检索此用户: /** * @View * * GET /users/{id} * @param integer $user (uses ParamConverter) */ public
id
username
firstname
lastname
年龄
性别
我使用端点GET/users/{id}
和以下方法检索此用户:
/**
* @View
*
* GET /users/{id}
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user) {
return $user;
}
该方法返回用户及其所有属性
现在我想允许这样做:GET/users/{id}?attributes=id、username、sex
问题:
我是否错过了FOSRestBUndle、JMSserializer或SensioFrameworkExtraBundle自动实现的功能?请求中的注释、方法、关键字还是其他
否则,实现这一目标的最佳方式是什么
代码
我想这样做:
/**
* @View
* @QueryParam(name="attributes")
*
* GET /users/{id}
*
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user, $attributes) {
$groups = $attributes ? explode(",", $attributes) : array("Default");
$view = $this->view($user, 200)
->setSerializationContext(SerializationContext::create()->setGroups($groups));
return $this->handleView($view);
}
并为每个属性创建一个组:
use JMS\Serializer\Annotation\Groups;
class User {
/** @Groups({"id"}) */
protected $id;
/** @Groups({"username"}) */
protected $username;
/** @Groups({"firstname"}) */
protected $firstname;
//etc
}
你可以通过小组来完成,如你所示。也许更优雅的解决方案是实现您自己的解决方案。还有一些是ExclutionStrategyInterface的实现 因此,假设您调用了您的策略SelectFieldsStrategy。一旦实现了它,就可以非常轻松地将其添加到序列化上下文中:
$context = new SerializationContext();
$context->addExclusionStrategy(new SelectFieldsStrategy(['id', 'name', 'someotherfield']));
我的实施基于: 退出策略:
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;
class FieldsExclusionStrategy implements ExclusionStrategyInterface {
private $fields = array();
public function __construct(array $fields) {
$this->fields = $fields;
}
public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext) {
return false;
}
public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext) {
if (empty($this->fields)) {
return false;
}
if (in_array($property->name, $this->fields)) {
return false;
}
return true;
}
}
/**
* @View
* @QueryParam(name="fields")
*
* GET /users/{id}
*
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user, $fields) {
$context = new SerializationContext();
$context->addExclusionStrategy(new FieldsExclusionStrategy($fields ? explode(',', $fields) : array()));
return $this->handleView($this->view($user)->setSerializationContext($context));
}
GET /users/{id}?fields=id,username,sex
控制器:
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;
class FieldsExclusionStrategy implements ExclusionStrategyInterface {
private $fields = array();
public function __construct(array $fields) {
$this->fields = $fields;
}
public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext) {
return false;
}
public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext) {
if (empty($this->fields)) {
return false;
}
if (in_array($property->name, $this->fields)) {
return false;
}
return true;
}
}
/**
* @View
* @QueryParam(name="fields")
*
* GET /users/{id}
*
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user, $fields) {
$context = new SerializationContext();
$context->addExclusionStrategy(new FieldsExclusionStrategy($fields ? explode(',', $fields) : array()));
return $this->handleView($this->view($user)->setSerializationContext($context));
}
GET /users/{id}?fields=id,username,sex
端点:
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;
class FieldsExclusionStrategy implements ExclusionStrategyInterface {
private $fields = array();
public function __construct(array $fields) {
$this->fields = $fields;
}
public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext) {
return false;
}
public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext) {
if (empty($this->fields)) {
return false;
}
if (in_array($property->name, $this->fields)) {
return false;
}
return true;
}
}
/**
* @View
* @QueryParam(name="fields")
*
* GET /users/{id}
*
* @param integer $user (uses ParamConverter)
*/
public function getUserAction(User $user, $fields) {
$context = new SerializationContext();
$context->addExclusionStrategy(new FieldsExclusionStrategy($fields ? explode(',', $fields) : array()));
return $this->handleView($this->view($user)->setSerializationContext($context));
}
GET /users/{id}?fields=id,username,sex
您知道有没有办法将所有这些逻辑放在注释中(直接放在@View内或放在新注释内)?实际上,我需要在任何地方都排除字段,并且每个端点中的代码将严格相同。我对php和symfony非常陌生,因此如果您有一些链接,我将不胜感激。:)这当然是可能的,但我从未做过自定义注释,因此我无法真正帮助您实现指导原则,您必须自己研究这一部分:)关于如何使用这种方法处理相关实体,有什么想法吗?在PropertyMetadata中,似乎没有任何信息表明给定字段是一个对象。我发现:
$context->getDepth()
可以用于此。在我的例子中,我正在检查它是否超过1。