gpt4 book ai didi

php - 通过 onDelete 删除实体时 Doctrine Cascade={remove} 不起作用 ="CASCADE"

转载 作者:行者123 更新时间:2023-12-03 23:18:49 35 4
gpt4 key购买 nike

我在使用 Doctrine 2 的实体之间的级联关系时遇到了问题。

我有一个与父事件相关的 Media 实体:

class Media
{

/**
* @ORM\OneToOne(targetEntity="Event", mappedBy="media")
*/
private $event;

public function getEvent()
{
return $this->event;
}

public function setEvent(Event $event)
{
$this->event = $event;
}

}

每个事件都与媒体(双向)相关,也与导入实体相关。

class Event
{

/**
* @ORM\JoinColumn(name="media", referencedColumnName="id", onDelete="SET NULL")
* @ORM\OneToOne(targetEntity="Media", inversedBy="event", cascade={"persist", "remove"}, orphanRemoval=true)
*/
private $media;

public function getMedia()
{
return $this->media;
}

public function setMedia(Media $media = null)
{
$this->media = $media;
}


/**
* @ORM\JoinColumn(name="import", referencedColumnName="id", nullable=true, onDelete="CASCADE")
* @ORM\ManyToOne(targetEntity="Import")
*/
private $import;

public function getImport()
{
return $this->import;
}

public function setImport(Import $import = null)
{
$this->import = $import;
}

}

预期行为如下:

  • Event 实体在其父 Import 被删除时会自动删除(与 onDelete="CASCADE" 的 ManyToOne 关系)。
  • Event 实体还包含对 Media 实体的引用(OneToOne 关系),删除事件时必须删除该实体。

两者都运行良好:

  • 如果我删除导入,所有相关事件都会被删除。
  • 如果我删除某个事件,相关媒体也会被删除。

但是,如果我删除导入,虽然事件被删除,但与已删除事件相关的媒体不会

对可能发生的事情有什么想法吗?谢谢!

最佳答案

您所描述的问题是预期的行为。 onDelete="CASCADE" 选项强制执行由数据库内部执行的行为,而选项 cascade={"remove"} 通过 Doctrine 处理并应用于以下对象:如所述 in the documentation 在内存中执行:

Cascade operations are performed in memory. That means collections and related entities are fetched into memory (even if they are marked as lazy) when the cascade operation is about to be performed. This approach allows entity lifecycle events to be performed for each of these operations.

这两种方法都是有效的,但它们意味着不同的事情,如所讨论的 in this section .


您的设置实际发生的情况是,您希望在您的场景中混合使用 onDelete="CASCADE"cascade={"remove"} 一起操作,这由于其本性,他们不能。

事实上,由于 Import 中没有 cascade={"remove"} 的反面,当您删除 Import:

  • 在数据库中对与Import对应的表执行DELETE操作
  • 由于表中用于事件的外键,与您的导入相关的事件将被直接在数据库中删除

从那里开始,不会执行任何其他操作,因为用于 Media 的表没有任何引用 Event 表的外键(因为它位于协会)。


您可以执行以下两件事来实现此目的:

反转媒体/事件关联并在 Media 表上添加 onDelete="CASCADE"

Media.php

/**
* @ORM\OneToOne(targetEntity="Event", inversedBy="media")
* @ORM\JoinColumn(onDelete="CASCADE")
*/
private $event;

Event.php

/**
* @ORM\OneToOne(targetEntity="Media", mappedBy="event")
*/
private $media;

通过这种方法,删除数据库中的 Import 条目必然会删除相关的 Event 条目,并且通过相同的机制,相关的 Media 将被删除。被删除(所有这些都是由您的数据库直接完成的,Doctrine 只是在 Import 表上发出了一个 DELETE 操作)。

Import中添加反面并使用cascade={"remove"}

如果使用 cascade={"remove"}Import 中添加反向 OneToMany,则使用实体管理器执行的删除操作将是级联到相关的 Event 实体,该实体还将删除操作级联到任何关联的 Media

如果您希望为这些实体执行生命周期事件,这会很有用。


这并不意味着您必须在两种方法之间进行选择。该文档说明如下:

You should be aware however that using strategy 1 (CASCADE=REMOVE) completely by-passes any foreign key onDelete=CASCADE option, because Doctrine will fetch and remove all associated entities explicitly nevertheless.

话虽这么说,如果您希望数据库保持正确的状态,那么除了 cascade={"remove"} 之外,还有 onDelete=CASCADE 是有意义的。例如,如果您直接执行DELETE查询(不使用实体管理器),则在没有onDelete=CASCADE的情况下不会删除相关条目,并且您的RDBMS很可能会提示无效外键约束。

关于php - 通过 onDelete 删除实体时 Doctrine Cascade={remove} 不起作用 ="CASCADE",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48852654/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com