如何在原则 2 中删除没有 EntityManager#remove(..) 的集合元素



我有一个像EntityA OneToMany EntityB这样的经典结构。实现为双向关系:

  • EntityB具有类型 EntityA 的属性$entityA
  • EntityA有一个属性$entityBs,其中包含EntityB元素的ArrayCollection

现在我想删除一些EntityB元素。它将像这样工作:

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

但我希望能够"说"$myEntityA->removeEntityB($entityB),而不需要关心其他任何事情。一个优点是,我可以实现一个方法EntityA#replaceEntityBs(ArrayCollection $entityBs),它只是删除所有EntityA#$entityBs并将它们替换为给定的元素。

是否有可能/如何直接从关系的反侧删除集合的元素(当然无需将EntityManager传递到实体中)?

解决方案是从EntityB中删除对EntityA的引用(第一个)。在这种情况下,教义将试图在没有的情况下坚持EntityB。但是如果我们将其与 orphanRemoval=true 结合起来,我们将得到目标结果:

class EntityA
{
    ...
    /**
     * @var ArrayCollection
     * @ORMOneToMany(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
     *
     * @ORMManyToOne(targetEntity="EntityA", inversedBy="entityBs")
     * @ORMJoinColumns({
     *   @ORMJoinColumn(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(应该更新),则会导致删除它们,并且仅保留新元素。

这是一个解决方案,可以按预期工作:

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);
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新