Doctrine - 删除子记录时删除父关联

时间:2016-08-25 10:35:25

标签: php symfony doctrine-orm doctrine

我有一个FileUpload实体,它是使用以下关联的其他实体的子实体:

    /**
     * @ORM\ManyToOne(targetEntity="FileUpload", cascade={"persist", "remove"} )
     * @ORM\JoinColumn(name="image_id", referencedColumnName="id")
     */
     protected $image;

FileUpload实体包含有关上传文件的各种信息以及标记为删除的布尔字段(由表单上的复选框处理)。我试图找到一种管理此删除过程的好方法,而不必在具有FileUpload实体的每个实体中复制代码。

我尝试创建一个用doctrine.event_listener标记的服务来删除postUpdate()中的FileUpload,但是由于仍然存在与FileUpload的父关联,因此失败了。有没有人知道在删除FileUpload时清除任何关联的方法?或者处理这个过程的任何其他方法?

1 个答案:

答案 0 :(得分:1)

对不起,迟到了。现在我明白你的问题。

在你所描述的关系中,必须是关系的所有者。如果让我们说A与B有关并且假设A是关系的所有者,则意味着A控制了关系的所有方面,因此如果没有A这样说就不能删除B.

考虑数据库的外键关系。只要数据库是关系的一部分并且不是关系的所有者(这是您当前的问题),数据库将不允许您删除该行。

如果你进入一个需要删除FileUpload的地方而不知道与它有关系的Comment,你的应用程序/数据库设计可能会遇到架构问题。如果您知道在要删除文件的位置与FileUpload有关系的Comment,那么orphanRemoval就是您所需要的。删除它的方式不是要求管理员将其删除(因为如果没有关系所有者的批准,它就无法执行此操作,如上例所示)。相反,你要求关系的所有者删除它像这样的

//for OneToOne relation
$comment->setFileUpload(null);

//for OneToMany relation
$comment->getFileUpload()->removeElement($fileUpload);

在上面的语句之后调用flush,它应该工作。同样对于OneToMany,请确保初始化

$this->fileUpload = new ArrayCollection(); 

在Comment实体构造函数中。

注意1:如前所述,小心使用孤立删除导致它无法正常工作,因为您可能会对管理器的刷新功能有所了解。在一个对象作为一个孤儿的教义工作单元市场之后,即使你在它上面调用了刷新,它也会被删除。找到了解决这个问题的方法(使用docline onFlush事件),但最好不要这样做并尽量避免这种情况。

注意2:orphanRemoval在数据库中具有硬删除的作用。如果您需要将此代码添加到doctrine订阅者或onFlush侦听器

public function onFlush(OnFlushEventArgs $args)
{
    foreach ($args->getEntityManager()->getUnitOfWork()->getScheduledEntityDeletions() as $entity) {

        if ($entity instanceof SoftRemovableInterface) {
            $args->getEntityManager()->remove($entity);
            $args->getEntityManager()->persist($entity);
            $entity->remove();
        }

        $args->getEntityManager()->getUnitOfWork()->computeChangeSet($args->getEntityManager()->getClassMetadata(get_class($entity)), $entity);
    }
}

如果remove + persist调用将实体从工作单元中的孤立删除列表中取出(在NOTE1中刷新实体的修复的一部分,这是唯一的方法,我发现你可以停止在通过学说标记之后删除一个孤儿,并且$ entity-> remove();是SoftRemovableInterface的方法,它处理软删除,如

class Comment implements SoftRemovableInterface
{
    /........../
    function remove()
    {
        $this->deleted = true;
    }
}

希望这能为你的问题带来一些启示。快乐的编码。

Alexandru Cosoi