从实体的数组集合中删除一个或多个项时,symfony 4.4串行化程序问题

2022-07-15 00:00:00 serialization php symfony symfony4

我注意到symfony 4.4序列化程序有一个不寻常的问题,我使用该序列化程序在rest API的控制器中进行实体数据序列化。

在正常情况下,它工作得很好,但如果我想序列化包含属性类型数组集合的实体,并且我删除了一个数组集合项而没有保存实体,它会输出包含key=&>值对的数组集合,而不是对象的数组。

这是一个快速示例:

<?php

use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentSerializerSerializerInterface;

use AppEntitySomeEntity;

class BaseController extends AbstractController
{

/**
 * @Route("/test/{testEntityId}", methods={"GET"}, name="api.v1.test")
 */
public function getTestResult(string $testEntityId, SerializerInterface $serializer)
{
    $testEntityRepository = $this->getDoctrine()->getRepository(TestEntity::class);
    $testEntity = $this->testEntityRepository->findOneBy($testEntityId);

    // ## > The code in this scope messes up with the serializer
    if ($testEntity && $testEntity->hasSomeItems()) {
        $someItem = $testEntity->getSomeItems()->getFirst();
        $testEntity->removeSomeItem($someItem);
    }

    $serialized_data = $this->serializer->serialize($entity, 'json', ['groups' => ['test']]);

    $headers = ['Content-type' => 'application/json'];
    return new Response($serialized_data, 200, $headers);
}

}

这将返回

{ "someItems": [ "1": { someItem 02 object }, "2": { someItem 03 object }, etc. ] }

而不是

{ "someItems": [ { someItem 02 object }, { someItem 03 object }, etc. ] }

正常。

发生这种情况的原因是,emoveSomeItem($ome Item)调用ArrayCollection的RemovveElement方法,该方法删除数组键为0的项,其余项保持其键不变。

如果我将以下行强制到symfony的ArrayCollection emoveElement方法中:$this->elements = array_values($this->elements);重置数组项键的顺序,我成功地获得了正常响应。

我需要一个解决方案来修复控制器中的这个问题,而不是更改symfony的核心代码。使用实体管理器保存实体是不适用的,因为我只需要从数组集合中移除一些旧的API客户端的不兼容项,以保持向后兼容性,并且不想持久保存这样的更改。

有什么好主意吗?

提前感谢!


解决方案

我在gihub上发现了一些相关的争论,找到了在实体移除项的方法中对数组集合项重新索引的解决方案:

<?PHP

namespace AppEntity;

use DoctrineCommonCollectionsArrayCollection;
use AppEntitySomeItem;

class SomeEntity
{
    private $someItems;


    public function __construct()
    {
        parent::__construct();
        $this->someItems = new ArrayCollection();
    }

    public function removeSomeItem(SomeItem $someItem): self
    {
        if ($this->someItems->contains($someItem)) {
            $this->someItems->removeElement($someItem);

            // Reindex array elements to avoid problems with data serialization
            $this->someItems = new ArrayCollection($this->someItems->getValues());
        }

        return $this;
    }
}

相关文章