Переиндексация элементов ArrayCollection в RESTAPI

Представьте, у меня есть коллекция массивов $items, и я реализовал метод removeItem в своем классе сущностей SomeEntity,

public function removeItem(Item $item)
{
    $this->items->removeElement($item);
    return $this;
}

и действие контроллера, которое получает запрос PATCH:

public function patchAction(Request $request, SomeEntity $entity) {
    $form = ...;

    $form->handleRequest($request);
    if ($form->isValid()) {
        ...
        $this->get('doctrine.orm.entity_manager')->flush();

        return $entity;
    }

    return $form;
}

Представьте, что экземпляр класса SomeEntity содержит элементы как [0 => {ITEM}, 1 => {ITEM}, 2 => {ITEM}, 3 => {ITEM}] (индексированный массив объектов). Если вы отправите запрос на getAction и получите объект SomeEntity в своем фронт-проекте в формате JSON, тип этих элементов в объекте будет индексированным массивом объектов (вы можете перебирать их с помощью методов массива), но если вы удалите одного или нескольких из объекта с методом PATCH и получить ответ JSON, вы получите тип Object с объектами в нем, потому что некоторые ключи были удалены после запроса PATCH, а объект класса SomeEntity в ответе больше не содержит индексированный массив, вместо него будет объект объектов. Это связано с тем, что при преобразовании массива в объект json вы можете получить два разных результата.

  1. массив объектов (массивов), если ключи проиндексированы (например: 0,1,2,3,...)
  2. объект объектов (массивов), если ключи не проиндексированы (например: 0,2,3,6,...)

В данный момент я решаю эту проблему, изменяя (вручную воссоздавая элементы) существующий метод removeItem в классе сущностей, например:

public function removeItem(Item $item)
{
    $this->items->removeElement($item);

    if (!$this->items->isEmpty()) {
        $items = new ArrayCollection();
        foreach ($this->items as $item) {
            $items->add($item);
        }

        $this->items = $items;
    }

    return $this;
}

Может быть, есть лучший способ решить эту проблему? Как решить эту проблему?

Я использую FOSRestBundle и JmsSerializerBundle.


person xurshid29    schedule 07.02.2016    source источник


Ответы (1)


Похоже, это распространенная проблема — см. https://github.com/schmittjoh/JMSSerializerBundle/issues/373 для тех, у кого возникла эта проблема. Определенно есть более короткий способ решить эту проблему в ваших функциях, где вы удаляете элементы, чем снова перебирать каждый элемент:

public function removeItem(Item $item)
{
    $this->items->removeElement($item);
    $this->items= new ArrayCollection($this->items->getValues());

    return $this;
}

В этом билете перечислены другие обходные пути, которые могут соответствовать или не соответствовать вашим потребностям. Если вам нужно глобальное решение, вы можете переопределить класс JsonSerializationVisitor, который приводит к массиву.

person Jason Roman    schedule 07.02.2016
comment
Спасибо за вашу помощь, переопределение JsonSerializationVisitor посетителя выглядит лучшим решением, чем мое. - person xurshid29; 08.02.2016
comment
Если это работает для вас (по предоставленной мной ссылке), дайте мне знать, и я добавлю этот ответ здесь (или отредактируйте свой вопрос или даже добавьте свой собственный ответ и примите его) - person Jason Roman; 08.02.2016