FOSRestBundle:请求中要求的属性函数中的部分响应


FOSRestBundle: partial response in function of attributes asked in the request

上下文

我发现了很多关于使用 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']));