Symfony 4 и Doctrine 2 сериализуются после удаления (первого) элемента из коллекции, что приводит к преобразованию в объект JSON вместо массива - PullRequest
1 голос
/ 11 марта 2019

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

У меня есть сущность 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"
},

Затем удаляю элемент FIRST:

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

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

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

{
    "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);

1 Ответ

0 голосов
/ 03 июля 2019

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

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

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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...