Php FOSRestBundle:请求中请求的属性函数中的部分响应 上下文

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

我发现了很多关于FOSRest的部分API响应的问题,所有答案都基于JMS序列化程序选项(排除、包含、组等)。它工作得很好,但我试图实现一些不太“静态”的东西

假设我有一个具有以下属性的用户:
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。