Doctrine manyToMany 返回 PersistentCollection 而不是 ArrayCollection

2022-01-03 00:00:00 php symfony php-7 doctrine-orm

我正在使用 Symfony 3.1 和 Doctrine 2.5.

I'm working with Symfony 3.1 and Doctrine 2.5.

我像往常一样设置了 manyToMany 关系:

I setup a manyToMany relationship as I always do :

manyToMany:
        placeServices:
            targetEntity: AcmeMyBundleEntityPlaceService
            joinTable:
                name: place_place_service
                joinColumns:
                    place_id:
                        referencedColumnName: id
                inverseJoinColumns:
                    place_service_id:
                        referencedColumnName: id

并为我的实体添加方法

    protected $placeServices;

    ...

    public function __construct()
    {
        $this->placeServices = new ArrayCollection();
    }

    ...

    /**
     * @return ArrayCollection
     */
    public function getPlaceServices(): ArrayCollection
    {
        return $this->placeServices;
    }

    /**
     * @param PlaceServiceInterface $placeService
     * @return PlaceInterface
     */
    public function addPlaceService(PlaceServiceInterface $placeService): PlaceInterface
    {
        if(!$this->placeServices->contains($placeService)) {
            $this->placeServices->add($placeService);
        }

        return $this;
    }

    /**
     * @param PlaceServiceInterface $placeService
     * @return PlaceInterface
     */
    public function removePlaceService(PlaceServiceInterface $placeService): PlaceInterface
    {
        if($this->placeServices->contains($placeService)) {
            $this->placeServices->removeElement($placeService);
        }

        return $this;
    }

问题是,当我加载我的实体时,Doctor 在 $this->placeServices 属性中放置了一个 PersistentCollection.这听起来不是一个大问题,除了当我构建一个表单来连接这两个实体时(一个简单的多个复选框,具有 symfony 表单类型),当 $form->handleRequest() 被触发时,Doctrine 尝试注入新数据在我的实体中,如果 get/add/remove 方法未使用 ArrayCollection,则会抛出错误.

The thing is, when I load my entity, doctrine put a PersistentCollection in the $this->placeServices property. This does not sound like a big problem, except that when I build a form to connect those two entities (a simple multiple checkboxes with symfony form type), when $form->handleRequest() is triggered, Doctrine try to inject the new data in my entity, and throw an error if get/add/remove method are not using ArrayCollection.

我可以强制我的 getter/add/remove 方法将 PersistentCollection 转换为 ArrayCollection(使用 unwrap 方法),但随后建立的关系不会持久化.

I can force my getter/add/remove methods to transforme the PersistentCollection to ArrayCollection (using unwrap method) but then the relations made are not persisted.

我找到了一种解决方法,如果我在关系上设置 fetch="EAGER",则该属性将使用 ArrayCollection 进行初始化,并且该关系将保持不变.但我不确定这是一个好的解决方案.

I've found a workaround, if I set fetch="EAGER" on the relation the property is initialized with ArrayCollection, and the relation are persisted. But i'm not sure it's a good solution.

谢谢:)

推荐答案

只需使用 DoctrineCommonCollectionsCollection 接口而不是 ArrayCollection.ArrayCollection 和 PersistentCollection 实现了这个接口.

Just use DoctrineCommonCollectionsCollection interface instead of ArrayCollection. ArrayCollection and PersistentCollection implement this interface.

Doctrine 使用 PersistentCollection 来延迟加载实体.您说得对,使用 EAGER 并不总是一个好的解决方案 - 它可能会导致性能问题.

Doctrine uses PersistentCollection for lazy loading entities. You are right, using EAGER is not always a good solution - it can cause perfomance issues.

相关文章