关于使用Symfony / FosRestBundle / JMS序列化器实现字段白名单的建议

詹姆斯·克林克利

我目前正在学习如何使用Symfony 3(带有FOSRestBundle)和JMS序列化器来实现相对简单的API。我最近一直在尝试实现一种功能,以指定作为消费客户端的响应中应返回哪些字段(所请求的实体和关系中的两个字段)。例如;

  • /posts如果没有包含查询字符串,则将返回所有Post实体属性(例如title,body,posted_at等),但没有关系
  • /posts?fields[]=id&fields[]=title将仅返回帖子的ID和标题(但同样,没有关系
  • /posts?include[]=comment将包括上述内容,但包含Comment关系(及其所有属性)
  • /posts?include[]=comment&include[]=comment.author 会如上返回,但在每个评论中还会包含作者

尝试实施这是一件理智的事情吗?我最近对此进行了大量研究,我看不出我可以做到以下几点:1)限制对单个字段的检索,以及2)仅在明确要求了相关实体的情况下才返回它们。

我最初对这个概念有所了解,但是即使确保我的存储库仅返回Post实体(即没有评论),JMS序列化程序似乎也会触发所有相关实体的延迟加载,而我似乎也无法停止。我已经看到了一些诸如本示例这样的链接,但是这些修补程序似乎不起作用(例如,在该链接中,$object->__load()原始代码中的注释调用永远都不会到达。

我已经使用JMSSerializer的Group功能实现了一个基于关系的示例,但是当我理想地能够构建一个Doctrine Querybuilder实例,动态添加andWhere()调用并让序列化程序仅返回该确切数据而不加载时,我感到必须这样做很奇怪。在关系中。

对此我深表歉意,但已经坚持了一段时间,对此我将不胜感激!谢谢。

挑战者

您应该可以使用Groups排除策略来实现所需的目标。

例如,您的Post实体可能如下所示:

use JMS\Serializer\Annotation as JMS;

/**
 * @JMS\ExclusionPolicy("all")
 */
class Post
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Column(type="integer")
     *
     * @JMS\Expose
     * @JMS\Groups({"all", "withFooAssociation", "withoutAssociations"})   
     */
    private $id;

    /**
     * @ORM\Column(type="string")
     *
     * @JMS\Expose
     * @JMS\Groups({"all", "withFooAssociation", "withoutAssociations"})
     */
    private $title;

    /**
     * @JMS\Expose
     * @JMS\Groups({"all", "withFooAssociation"})
     *
     * @ORM\OneToMany(targetEntity="Foo", mappedBy="post")
     */
    private $foos;
}

这样,如果您的控制器操作返回Viewusing serializerGroups={"all"},则Response将包含您实体的所有字段。

如果使用serializerGroups={"withFooAssociation"},则响应将包含foos[]关联条目及其暴露的字段。

并且,如果使用serializerGroups={"withoutAssociation"},则foos关联将被序列化程序排除,因此将不呈现关联。

要从关联的目标实体(Foo实体)中排除属性,请在目标实体属性上使用相同Groups的属性,以获取链式序列化策略。

当您的序列化结构良好时,您可以serializerGroups在控制器中动态设置,以便根据includefields参数使用不同的组(即/posts?fields[]=id&fields[]=title)。例:

// PostController::getAction

use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerBuilder;

$serializer = SerializerBuilder::create()->build();
$context = SerializationContext::create();
$groups = [];

// Assuming $request contains the "fields" param
$fields = $request->query->get('fields');

// Do this kind of check for all fields in $fields
if (in_array('foos', $fields)) {
    $groups[] = 'withFooAssociation';
}

// Tell the serializer to use the groups previously defined
$context->setGroups($groups);

// Serialize the data
$data = $serializer->serialize($posts, 'json', $context);

// Create the view
$view = View::create()->setData($data);

return $this->handleView($view);

希望我能正确理解您的问题,对您有所帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

symfony / FOSRestBundle:空的JSON响应(使用symfony内置的序列化器)

带有 FOSRestBundle 的 Symfony 序列化程序?

使用FOSRestBundle将POST请求主体序列化为数组

FOSRestBundle中的JMS序列化程序重写组

Symfony + FOSRestBundle - 如何为使用自定义表单类型配置的字段允许 NULL 值?

使用FOSRestBundle w / Symfony 3.4路由多个REST控制器

使用 FOSRestBundle 在 Symfony 中编写 GET 路由

Symfony4 FOSRestBundle 尝试持久化 ManyToMany SQL 语法错误

如何使用JMS序列化器和Symfony2实现模型侧面加载

无法在Symfony 5上安装FOSRestBundle

Symfony2,FOSRestBundle-捕获异常

FOSRestBundle在Symfony 4.1中不起作用

路由中的Symfony fosrestbundle可选参数

Symfony 2-使代码保持干燥-FOSRestBundle

如何使用FOSRestBundle和symfony表单处理嵌套的json

使用Symfony,jQuery,FOSRestBundle和NelmioCorsBundle进行CORS

Symfony将JMS序列化器与JsonResponse结合使用

如何使用FOSRestBundle向控制器的所有路由添加通用URI前缀?

使用FOSRestBundle REST API设置注册FOSUserBundle

FOSRESTBundle:如何在控制器级别更改序列化程序元数据目录

带有 FOSRestBundle 的 Symfony API:检测到循环引用

Symfony2 FOSRESTBundle REST API返回PDF

FOSRestBundle + Symfony 3.4:未重新分类休息类型

Symfony 3(FOSrestBundle)+ Angular 1 POST请求为空

FindAll()无法正常工作,Symfony 3 FosrestBundle API

Symfony4 的 FOSRestBundle 问题,204 没有内容响应

带有symfony 2.7和PHP 5.5.12的FOSRestBundle和JMSSerializerBundle

使用FOSRestBundle和FOSUserBundle具有RESTful身份验证的Symfony2 App

Symfony-使用FOSRestBundle和body_listener的过滤器请求没有注释?