0

私はEntityA OneToMany EntityBのような古典的な構造を持っています。双方向の関係として実装:Doctrine 2でEntityManager#remove(...)なしでコレクション要素を削除するにはどうすればよいですか?

  • EntityBArrayCollectionEntityBの要素を含むタイプEntityAのプロパティ$entityA
  • EntityA$entityBsを有するを有します。

ここで、EntityB個の要素を削除します。それはこのように動作します:

$entityManager->remove($myEntityB); 
$entityManager->flush(); 

しかし、私はちょうど何かを気にする必要はありませ$myEntityA->removeEntityB($entityB)を「言う」とすることができるようにしたいと思います。利点は、方法EntityA#replaceEntityBs(ArrayCollection $entityBs)を実装することができ、単にすべてEntityA#$entityBsを削除し、それらを指定された要素に置き換えることです。

は、それが/どのように(エンティティへEntityManagerを渡すことはもちろんなし)に直接関係の逆側からコレクションの要素を削除することは可能ですか?

答えて

0

解決策は、EntityB(最初)からEntityAへの参照を削除することです。この場合、DoctrineはEntityBをそのまま使用しようとします。我々はorphanRemoval=trueと組み合わせる場合でも、私たちは目指した結果を得るでしょう:

class EntityA 
{ 
    ... 
    /** 
    * @var ArrayCollection 
    * @ORM\OneToMany(targetEntity="EntityB", mappedBy="entityA", cascade={"persist"}, orphanRemoval=true) 
    */ 
    protected $entityBs; 
    ... 
    public function removeEntityB(EntityB $entityB) 
    { 
     $this->entityBs->removeElement($entityB); 
     $entityB->setEntityA(null); 
     return $this; 
    } 
    ... 
} 

class EntityB 
{ 
    ... 
    /** 
    * @var EntityA 
    * 
    * @ORM\ManyToOne(targetEntity="EntityA", inversedBy="entityBs") 
    * @ORM\JoinColumns({ 
    * @ORM\JoinColumn(name="entity_a_id", referencedColumnName="id") 
    * }) 
    */ 
    protected $entityA; 
    ... 
    /** 
    * @param EntityA $entityA 
    * @return EntityB 
    */ 
    public function setEntityA(EntityA $entityA = null) 
    { 
     $this->entityA = $entityA; 
     return $this; 
    } 
    ... 
} 
トピックオフ

:私は質問で述べたので利点があろうと、コレクション

の交換EntityA#replaceEntityBs(ArrayCollection $entityBs)のようなメソッドを実装することができます、私はここで可能な実装を共有したいと思います。

最初のナイーブな試みは、すべてEntityBsを削除してから、新しい要素を追加(永続化)することでした。

public function setEntityBs($entityBs) 
{ 
    $this->removeEntityBs(); 
    $this->entityBs = new ArrayCollection([]); 
    /** @var EntityB $entityB */ 
    foreach ($entityBs as $entityB) { 
     $this->addEntityB($entityB); 
    } 
    return $this; 
} 
public function removeEntityBs() 
{ 
    foreach ($this->getEntityBs() as $entityB) { 
     $this->removeEntityB($entityB); 
    } 
    return $this; 
} 

しかし含まsetEntityBs(...)既存EntityBsの入力コレクションの場合(つまり、更新されSHOLD)、それはそれらの削除と唯一の新しい要素が持続してしまったにつながりました。ここで

が望んだとして機能するソリューションです:

public function setEntityBs($entityBs) 
{ 
    $this->removeEntityBsNotInList($entityBs); 
    $this->entityBs = new ArrayCollection([]); 
    /** @var EntityB $entityB */ 
    foreach ($entityBs as $entityB) { 
     $this->addEntityB($entityB); 
    } 
    return $this; 
} 
private function removeEntityBsNotInList($entityBs) 
{ 
    foreach ($this->getEntityBs() as $entityB) { 
     if ($entityBs->indexOf($entityB) === false) { 
      $this->removeEntityB($entityB); 
     } 
    } 
} 
関連する問題