我目前正在学习如何使用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;
}
这样,如果您的控制器操作返回View
using serializerGroups={"all"}
,则Response将包含您实体的所有字段。
如果使用serializerGroups={"withFooAssociation"}
,则响应将包含foos[]
关联条目及其暴露的字段。
并且,如果使用serializerGroups={"withoutAssociation"}
,则foos
关联将被序列化程序排除,因此将不呈现该关联。
要从关联的目标实体(Foo
实体)中排除属性,请在目标实体属性上使用相同Groups
的属性,以获取链式序列化策略。
当您的序列化结构良好时,您可以serializerGroups
在控制器中动态设置,以便根据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);
希望我能正确理解您的问题,对您有所帮助。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句