【问题标题】:How to serialize slice of ArrayCollection using JMS Serializer?如何使用 JMS 序列化器序列化 ArrayCollection 切片?
【发布时间】:2016-05-12 20:09:40
【问题描述】:

我想序列化为 JSON 实体 CategoryPresentation 实体集合(见下文)以用于 REST API。

端点看起来像这样/api/v1/categories/1

当数据集很小并且Category 只有 5-10 个相关的Presentations 时,结果响应不会太大。但是,当Category 开始有 100 或 200 个相关的 Presentations 时,显然我不想返回所有这些,而是​​想“分页”结果,例如。调用端点时:

/api/v1/categories/1?page=2 - 只会返回“第二页”

/api/v1/categories/1/page=3 - 将返回“第三页”

甚至可以使用offsetlimit

/api/v1/categories/1?offset=20&limit=10

但问题是:如何让 JMS 序列化器只序列化集合的一部分?

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository")
 */
class Category
{

    /**
     * @var string
     * @ORM\Column(type="string")
     * @JMS\Expose()
     * @JMS\Groups({"get-category"})
     */
    private $title;


    // ...

    /**
     * @var ArrayCollection
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Presentation", mappedBy="categories", fetch="EXTRA_LAZY")
     * @JMS\Groups({"get-category"})
     * @JMS\Expose()
     */
    private $presentations;


    // ...

}

ps。我知道,例如,如果我想始终获得集合的 first 5 个元素,我可以添加 created @VirtualProperty 并切片学说 ArrayCollection,如下所示。但是这里的问题是我不能将偏移参数传递给这个方法。因为它会被 JMSSerializer 在某处内部调用...

/**
 * @JMS\VirtualProperty()
 *
 */
public function getFirstFivePresentations(){
    return $this->presentations->slice(0,5);
}

【问题讨论】:

  • 限制查询中的收集结果不是更有意义吗?而不是总是加载 100% 的结果并在事后尝试对它们进行切片?
  • @JasonRoman 如果关联的获取策略是LAZYEAGER,您的担忧是正确的。但是在我的情况下,我已将关联标记为EXTRA_LAZYdoctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/…@ORM\ManyToMany(targetEntity="Presentation", mappedBy="categories", fetch="EXTRA_LAZY"),这意味着该集合不会完全加载。并且所有 SELECT 查询都被推迟到我调用 slice(0,5) 的那一刻,这导致 SELECT xxx FROM presentation OFFSET 0 LIMIT 5
  • 难道你不能写一个自定义查询来检索你需要的东西吗?
  • @JasonRoman 我想我开始明白你的意思了......让我试试......
  • 是的,我不会简单地依赖这里的关联,尤其是对于 API,尤其是在水合作用可能真的会减慢检索速度的情况下

标签: php symfony serialization doctrine-orm jms-serializer


【解决方案1】:

您正在尝试在 REST API 中实施不正确的方法。每个实体都必须有自己的路径。

正确的做法是有两个不同的端点:

/api/v1/categories/1 -> 序列化类别没有演示文稿

/api/v1/categories/1/presentations -> 演示文稿的序列化集合

这里你应该使用分页

/api/v1/categories/1/presentations?offset=20&limit=10

【讨论】:

  • 我同意你的观点,在categories 资源中包含presentations 似乎不是教科书式的解决方案。但是,从我使用的应用程序中,我有一个视图,它显示了 /List of categories with a few sample presentations/,我不想从应用程序发出多个 API 请求来检索这些数据。而且我看到了更多类似场景的用例——应用程序的大多数视图都需要混合来自不同资源的数据......
  • Category 中创建属性$presentationPreviews 并且不要将其与学说注释映射,为其创建setter。将$presentations 排除在序列化之外。在控制器中,获取类别后,循环它们并使用存储库类获取它们的演示文稿(设置您喜欢的标准和限制)。使用$category->setPresentationPreviews($fetchedPresentations) 设置获取的演示文稿集合。配置序列化以序列化$presentationPreviews 属性。就是这样!
猜你喜欢
  • 2015-08-03
  • 2016-03-02
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多