我目前正在学习如何使用Symfony 3(带有FOSRestBundle)和JMS Serializer来实现相对简单的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 Serializer似乎触发了所有相关实体的延迟加载,我似乎无法停止这个。我已经看到了一些链接,例如this example但是这些修补程序似乎不起作用(例如在该链接中,在原始代码中从未到达注释掉的$object->__load()
调用。
我已经实现了relationship-based example of this using JMSSerializer's Group
functionality,但是当我理想情况下能够构建一个Doctrine Querybuilder实例,动态添加andWhere()
调用并让序列化程序返回时,我感到很奇怪。精确数据,无需加载关系。
我为此撒谎而道歉,但我已经坚持了一段时间,我很感激任何投入!谢谢。
答案 0 :(得分:2)
您应该能够通过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
返回serializerGroups={"all"}
,则响应将包含您实体的所有字段。
如果它使用serializerGroups={"withFooAssociation"}
,则回复将包含foos[]
个关联条目及其公开字段。
并且,如果它使用serializerGroups={"withoutAssociation"}
,则foos
关联将被序列化程序排除,因此不会呈现。
要从关联(Foo
实体)的目标实体中排除属性,请在目标实体属性上使用相同的Groups
以获得链式序列化策略。
当序列化结构良好时,您可以动态设置控制器中的serializerGroups
,以便根据include
和fields
参数使用不同的组(即{{1 }})。例如:
/posts?fields[]=id&fields[]=title
我希望我能正确理解你的问题,这足以帮助你。