2016-02-03 5 views
3

Я хочу сериализовать объект JSON Category с коллекцией объектов Presentation (см. Ниже) для использования в REST API.Как сериализовать срез ArrayCollection с помощью JMS Serializer?

конечная точка будет выглядеть примерно так /api/v1/categories/1

Когда набор данных невелик, и когда Category только имеет только 5-10 связанные Presentations то полученный ответ не слишком велик. Однако, когда Category начинает говорить о 100 или 200 связанных Presentations, то, очевидно, я не хочу возвращать их все, но хотел бы «разбивать страницы» на результаты, например. при вызове конечной точки:

/api/v1/categories/1?page=2 - будет возвращать только "2-ю страницу"

/api/v1/categories/1/page=3 - вернется "3-й странице"

или даже может быть с offset и limit:

/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; 


    // ... 

} 

пс. Я знаю, что, например, если я хочу получить всегда first 5 элементов коллекции, я могу добавить созданный @VirtualProperty и отрезать доктрину ArrayCollection, как показано ниже. Но проблема в том, что я не могу передать параметры смещения этому методу. Как она будет называться внутренне JMSSerializer где-то ...

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

Разве не было смысла ограничивать результаты сбора в вашем запросе, а не всегда загружать 100% из них и пытаться разрезать их после факта? –

+0

@JasonRoman ваша забота верна в случае, если стратегия сбора заявок является «LAZY» или «EAGER». Однако в моем случае я отметил ассоциацию как «EXTRA_LAZY» http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/tutorials/extra-lazy-associations.html '@ORM \ ManyToMany (targetEntity = "Presentation", mappedBy = "categories", fetch = "EXTRA_LAZY") ', что означает, что сбор не будет загружен полностью. И все запросы SELECT откладываются до момента, когда я вызываю 'slice (0,5)', что приводит к 'SELECT xxx FROM presentation OFFSET 0 LIMIT 5'. –

+0

Не могли бы вы просто написать пользовательский запрос, хотя бы получить то, что вам нужно? –

ответ

0

Вы пытаетесь осуществить неправильный подход в вашем REST API. Каждый объект должен иметь свой собственный путь.

Правильный путь должен иметь два различных конечных точек:

/api/v1/categories/1 -> Serialized категории без каких-либо презентаций

/api/v1/categories/1/presentations -> Serialized коллекция presentaions

И здесь вы должны использовать пагинацию

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

+0

Я согласен с вами в том, что включение 'презентаций' в ресурс' categories', похоже, не является решением для учебников. Однако из приложения, которое я использую, у меня есть представление, которое показывает/Список категорий с несколькими примерами презентаций /, и я не хочу делать несколько запросов API из приложения для извлечения этих данных. И я вижу больше случаев использования для подобных сценариев - для большинства представлений приложения требуется сочетание данных из разных ресурсов .... –

+0

Создайте свойство '$ presentationPreviews' в' Category' и не сопоставляйте его с аннотациями доктрины, создайте для него сеттер. Исключить '$ presentation' из сериализации. В контроллере после того, как были выбраны категории, зациклируйте их и извлеките их презентации, используя класс репозитория (задайте критерии и ограничения, которые вам нравятся). Установите выбранную коллекцию презентаций, используя '$ category-> setPresentationPreviews ($ fetchedPresentations)'. Настройте сериализацию для сериализации свойства '$ presentationPreviews'. Вот и все! – Jekis