web-dev-qa-db-ja.com

Doctrine manyToManyはArrayCollectionの代わりにPersistentCollectionを返します

Symfony 3.1とDoctrine 2.5で作業しています。

私はいつものようにmanyToMany関係をセットアップします:

manyToMany:
        placeServices:
            targetEntity: Acme\MyBundle\Entity\PlaceService
            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;
    }

問題は、エンティティをロードするときに、doctrine $ this-> placeServicesプロパティにPersistentCollectionを追加します。これは大きな問題のようには聞こえません。これら2つのエンティティ(symfonyフォームタイプの単純な複数のチェックボックス)を接続するフォームを構築するとき、$ form-> handleRequest()がトリガーされるとき、Doctrineに新しいデータを注入しようとしますエンティティ。get/ add/removeメソッドがArrayCollectionを使用していない場合はエラーをスローします。

Getter/add/removeメソッドを使用してPersistentCollectionをArrayCollectionに変換することができます(unwrapメソッドを使用)。ただし、作成された関係は保持されません。

リレーションにfetch = "EAGER"を設定すると、プロパティがArrayCollectionで初期化され、リレーションが保持される場合、回避策が見つかりました。しかし、それが良い解決策であるかどうかはわかりません。

ありがとう:)

17
Thomas Piard

ArrayCollectionの代わりにDoctrine\Common\Collections\Collectionインターフェイスを使用してください。 ArrayCollectionおよびPersistentCollectionこのインターフェイスを実装します。

Doctrineは遅延読み込みエンティティにPersistentCollectionを使用します。 EAGERを使用することは常に良い解決策ではありません-パフォーマンスの問題を引き起こす可能性があります。

35
Artur Vesker