gpt4 book ai didi

php - 使用 Symfony/FosRestBundle/JMS Serializer 实现字段白名单的建议

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:43:52 25 4
gpt4 key购买 nike

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

    不包含查询字符串的
  • /posts 将返回所有 Post 实体属性(例如标题、正文、posted_at 等),但没有关系
  • /posts?fields[]=id&fields[]=title 将只返回帖子的 ID 和标题(但同样,没有关系)
  • /posts?include[]=comment 将包含上述内容,但具有 Comment 关系(及其所有属性)
  • /posts?include[]=comment&include[]=comment.author 会像上面那样返回,但也会在每条评论中包含作者

尝试和实现这种做法明智吗?我最近对此进行了大量研究,但我看不出我可以 1) 限制对单个字段的检索,以及 2) 仅在明确要求时才返回相关实体。

我对这个概念有过一些初步的尝试,但是即使确保我的存储库只返回 Post 实体(即没有评论),JMS Serializer 似乎会触发所有相关实体的延迟加载而且我似乎无法停止这个。我看到了一些链接,例如 this example然而修复似乎不起作用(例如在该链接中,注释掉的 $object->__load() 调用在原始代码中无论如何都不会到达。

我已经实现了 relationship-based example of this using JMSSerializer's Group functionality但是不得不这样做感觉很奇怪,当我理想地能够构建一个 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;
}

像这样,如果您的 Controller 操作返回 View使用 serializerGroups={"all"} ,响应将包含您实体的所有字段。

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

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

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

当你的序列化结构良好时,你可以动态设置 serializerGroups在你的 Controller 中,为了根据 include 使用不同的组和 fields参数(即 /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);

希望我正确理解了您的问题,这足以帮助您。

关于php - 使用 Symfony/FosRestBundle/JMS Serializer 实现字段白名单的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36212327/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com