禁用Doctrine外键约束
禁用Doctrine外键约束
我在我的模型中有一个关系:
/** * @ORM\ManyToOne(targetEntity="Page", cascade="persist") * @ORM\JoinColumn(name="page_id", referencedColumnName="id") */ private $parentPage;
当我删除父页面时,我会遇到以下错误:
完整性约束冲突:1451 无法删除或更新父行:外键约束失败
基本上,我的模型有一个页面和页面修订。当我删除页面时,我不想删除修订。我也想保留页面修订的page_id
(即不将其设置为null)。
如何使用Doctrine实现这一点?
问题原因:根据定义,如果没有将外键设置为null(onDelete="SET NULL")或级联删除操作(cascade={"remove"} | onDelete="CASCADE"),则无法删除指向外键的记录。
解决方法:一种解决方法是软删除(已经提到)。另一种方法是在删除之前,在preRemove事件处理程序(生命周期回调)中将一个额外的removed_page_id列与page_id同步。以下是代码示例:
在Revision类中:
/** * \ManyToOne(targetEntity="Page", cascade="persist") * \JoinColumn(name="page_id", referencedColumnName="id", onDelete="SET NULL") */ private $parentPage; /** * int * \Column(type="integer", name="removed_page_id", nullable=true) */ protected $removedPageId;
然后在Page类中:
/** * \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(); }
或者,您当然可以在构建Revision对象时已经设置正确的removedPageId值,那么您甚至不需要在删除时执行生命周期回调。
保证约束需要额外的计算资源。应用程序服务器比数据库服务器更容易进行水平扩展,因此约束应该放在业务逻辑中。