我和我的一个模特有关系:
/**
* @ORM\ManyToOne(targetEntity="Page", cascade="persist")
* @ORM\JoinColumn(name="page_id", referencedColumnName="id")
*/
private $parentPage;
当我删除父页时,会出现以下错误:
Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails
基本上我的模型是一个页面,和页面修改。当我删除页面时,我不想删除修订。我还想保留页面修订版上的
page_id
(即不要将其设置为空)。我怎么能用教义做到这一点?
最佳答案
根据定义,如果不将外键设置为空(onDelete="SET NULL"
)或级联删除操作(There are two options-orm level:cascade={"remove"}
数据库level:onDelete="CASCADE"
),则无法删除外键指向的记录。可以选择setting a default value of a still existing record,但您必须手动完成,我认为Doctrine不支持这个out-of-the-box
(如果我错了,请纠正我,但在这种情况下,无论如何都不需要设置默认值)。
这种严格性反映了具有外键约束的概念;正如@théo所说:
fk是为了确保数据的一致性。
软删除(前面已经提到过)是一种解决方案,但是您还可以添加一个额外的removed_page_id
列,在您在page_id
事件处理程序(生命周期回调)中删除它之前与preRemove
同步。我想知道这样的信息是否有价值,但我想你对它有些用处,否则你不会问这个问题。
我绝对不是说这是一个好的做法,但它至少是一些东西,你可以用你的优势案件。所以下面是:
在您的Revision
中:
/**
* @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;
然后在您的
Page
中:/**
* @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();
}
当然,您也可以在构建
$removedPageId
期间设置正确的Revision
值,然后甚至不需要在remove时执行生命周期回调。