Сериализация Symfony 4 и Doctrine 2 после удаления (первого) элемента из коллекции приводит к преобразованию в объект JSON вместо массива

У меня большие проблемы с сериализацией коллекции, из которой я удалил первый элемент.

У меня есть объект CompaniesCollection с отношением Many2Many к объекту Company.

/**
 * @ORM\ManyToMany(targetEntity = "App\Entity\Company")
 * @Groups({"get-by-collection-owner"})
 */
private $items;

Когда я извлекаю объект из этой коллекции, я получаю элементы в виде массива из двух элементов, которые я добавил в первую очередь. я сериализую это

{
    "id": 19,
    "name": "collection dummy name",
    "items": [
        {
            "id": 431,
            "name": "Company 1"
        },
        {
            "id": 435,
            "name": "Company 2"
        }
    ],
    "createdAt": "2019-03-11T13:55:43+01:00",
    "updatedAt": "2019-03-11T15:48:57+01:00"
},

Затем я удаляю ПЕРВЫЙ элемент:

    $collection->removeItem($companyToRemove);
    $em = $this->getDoctrine()->getManager();
    $em->persist($collection);
    $em->persist($companyToRemove);
    $em->flush();

    $results = $companiesCollectionRepository->getCollections($companyLoader->getCurrentCompany());

Сериализуем $results и получаем не массив из одного элемента, а объект с ключом второго элемента из предыдущего массива элементов:

{
    "id": 19,
    "name": "collection dummy name",
    "items": {
        "1": {
            "id": 435,
            "name": "Company 2"
        }
    },
    "createdAt": "2019-03-11T13:55:43+01:00",
    "updatedAt": "2019-03-11T15:52:48+01:00"
},

Когда я перезагружаю страницу и получаю этот объект, коллекция снова представляет собой массив из одного элемента, а не объект. Очевидно, что Doctrine не получает новых результатов из базы данных, а возвращает уже загруженные в память данные.

И сериализатор, скорее всего, рассматривает этот «массив» как «объект», потому что он начинается не с 0 для ключа первого элемента массива, а с ключа 1.

Есть ли способ сделать этот запрос снова, чтобы я получил свежесгенерированные ключи или обновил эти ключи?

Обновлено:

На самом деле я наконец нашел простое решение для этого: обновить после сброса

    $collection->removeItem($companyToRemove);
    $em = $this->getDoctrine()->getManager();
    $em->persist($collection);
    $em->persist($companyToRemove);
    $em->flush();
    $em->refresh($collection);
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
0
830
1

Ответы 1

Я столкнулся с той же проблемой. И вот еще одно решение, которое, кажется, работает для меня.

Пользовательский нормализатор, который будет использоваться для коллекций с «дырками» в ключах:

namespace App\Serializer\Normalizer;

use Doctrine\Common\Collections\Collection;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerAwareTrait;

class DoctrineCollectionNormalizer implements NormalizerInterface, SerializerAwareInterface
{
    use SerializerAwareTrait;

    public function normalize($object, $format = null, array $context = array()): array
    {
        /* @var $object Collection */
        $values = $object->getValues();
        $object->clear();
        foreach ($values as $k => $value) {
            $object->set($k, $value);
        }

        return $this->serializer->normalize($object, $format, $context);
    }

    public function supportsNormalization($data, $format = null): bool
    {
        if ($data instanceof Collection) {
            $keys = $data->getKeys();
            $count = count($keys);
            $lastKey = (int) array_pop($keys);
            return $count && $lastKey !== $count-1;
        }
        return false;
    }
}

Сегодня я столкнулся с той же проблемой. Спасибо @storm за пример кода. Пока нет лучшего решения, я буду использовать это

Max Schindler 16.10.2019 10:44

Другие вопросы по теме