上下文
我发现了很多关于使用 FOSRest 进行部分 API 响应的问题,所有答案都基于 JMS 序列化程序选项(exlude、include、groups等)。它工作正常,但我试图实现一些不那么"静态"的东西。
假设我有一个具有以下属性的用户:id
username
firstname
lastname
age
sex
我使用端点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
}
我基于伊戈尔答案的实现:
排行策略:
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
正如你所展示的,你可以通过小组来做到这一点。也许更优雅的解决方案是实现您自己的排除策略。@Groups和其他也是ExclusionStrategyInterface的实现。
所以,假设你称你的策略为SelectFieldsStrategy。实现它后,您可以非常轻松地将其添加到序列化上下文中:
$context = new SerializationContext();
$context->addExclusionStrategy(new SelectFieldsStrategy(['id', 'name', 'someotherfield']));