禁用原则外键约束 [英] Disable Doctrine foreign key constraint

查看:93
本文介绍了禁用原则外键约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一种模型上有关系:

I have a relationship on one of my models:

/**
* @ORM\ManyToOne(targetEntity="Page", cascade="persist")
* @ORM\JoinColumn(name="page_id", referencedColumnName="id")
*/
private $parentPage;

当我删除父页面时,出现此错误:

And when I delete the parent page, I get this error:

Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails

基本上我的模型是页面和页面修订版。删除页面时,我不想删除。我也想在页面修订版上保留 page_id (即不要将其设置为null)。

Basically my models are a page, and page revision. When I delete the page I don't want to delete the revisions. I also want to keep the page_id on the page revisions (i.e. not set it to null).

如何我是用Doctrine做的吗?

How can I do this with Doctrine?

推荐答案

通过定义,您不能删除外键为指向而不将键设置为null( onDelete = SET NULL )或级联删除操作(有两个选项-ORM级别: cascade = { remove} |数据库级别: onDelete = CASCADE。)。
还有设置仍然存在的记录的默认值,但是您必须手动执行此操作,我不认为Doctrine支持此现成的 (如果我错了,请纠正我,但是在这种情况下无论如何都不要设置默认值。)

By definition you cannot delete the record that the foreign key is pointing at without setting the key to null (onDelete="SET NULL") or cascading the delete operation (There are two options - ORM Level: cascade={"remove"} | database level: onDelete="CASCADE").
There is the alternative of setting a default value of a still existing record, but you have to do that manually, I don't think Doctrine supports this out-of-the-box(please correct me if I am wrong, but in this case setting a default value is not desired anyway).

这种严格性反映了具有外键约束的概念;就像@Théo所说:

This strictness is reflecting the concept of having foreign key constraints; like @Théo said:


FK是为了确保数据一致性

软删除(已经提到)是一种解决方案,但是您还可以做的是添加一个额外的 removed_pa​​ge_id 列您与 page_id 进行了同步,就在 preRemove 事件处理程序中将其删除之前(生命周期回调)。这些信息是否具有任何价值,我想知道,但我想您对此有一定用处,否则您不会问这个问题。

Soft delete (already mentioned) is one solution, but what you could also do is add an additional removed_page_id column that you sync with the page_id just before you delete it in a preRemove event handler (life cycle callback). Whether such information has any value I wonder but I guess you have some use for it, otherwise you wouldn't ask this question.

我肯定是不主张这是一个好习惯,但这至少可以用于边缘情况。因此,符合以下条件的行:

I am definitely not claiming this is good practice, but it is at least something that you can use for your edge case. So something in the line of:

在您的修订版中:

/**
 * @ORM\ManyToOne(targetEntity="Page", cascade="persist")
 * @ORM\JoinColumn(name="page_id", referencedColumnName="id", onDelete="SET NULL")
 */
private $parentPage;

/**
 * @var int
 * @ORM\Column(type="integer", name="removed_page_id", nullable=true)
 */
protected $removedPageId;

然后在您的页面中:

/** 
 * @ORM\PreRemove 
 */
public function preRemovePageHandler(LifecycleEventArgs $args)
{
    $entityManager = $args->getEntityManager();
    $page = $args->getEntity();
    $revisions = $page->getRevisions();
    foreach($revisions as $revision){
        $revision->setRemovedPageId($page->getId());
        $entityManager->persist($revision);
    }
    $entityManager->flush();
}

当然,您可能已经设置了正确的 $在构造修订版的过程中,如果您删除了RemovePageId 的值,那么您甚至不需要在remove上执行生命周期回调。

Alternatively you could of course already set the correct $removedPageId value during construction of your Revision, then you don't even need to execute a life cycle callback on remove.

这篇关于禁用原则外键约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆