我有一个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时清除任何关联的方法?或者处理这个过程的任何其他方法?
答案 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