Doctrine orm 博士2预先删除一个域名
在我的模型中,我有 Terrain.php Lot.php 很多Doctrine orm 博士2预先删除一个域名,doctrine-orm,Doctrine Orm,在我的模型中,我有 Terrain.php Lot.php 很多 我试图删除一个地形,但以前我删除了所有与之相关的地块。当我尝试删除地形时,我得到一个错误SQLSTATE[23000]:完整性约束冲突在删除时,您仍然有一个从地块到地形的引用,这就是为什么您有完整性约束冲突 试试这个: /** * @ORM\Entity * @ORM\HasLifecycleCallbacks() */ class Terrain { /** * @var lots * * @OR
我试图删除一个地形,但以前我删除了所有与之相关的地块。当我尝试删除地形时,我得到一个错误
SQLSTATE[23000]:完整性约束冲突
在删除时,您仍然有一个从地块
到地形
的引用,这就是为什么您有完整性约束冲突
试试这个:
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
*/
class Terrain
{
/**
* @var lots
*
* @ORM\OneToMany(targetEntity="Lot", mappedBy="terrain")
*/
private $lotes;
/**
* @ORM\PreRemove
*/
public function deleteAllLots()
{
$lots = $this->getLots();
foreach ($lots as $lot) {
$this->lots->removeElement($lot);
$lot->terrain = null; //$lot->setTerrain(null); will be better, try to add getters and setters
}
}
}
如果要从数据库中删除lots
,应使用OneToMany
relation()的cascade
属性,如下所示:
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
*/
class Terrain
{
/**
* @var lots
*
* @ORM\OneToMany(targetEntity="Lot", mappedBy="terrain", cascade={"remove"})
*/
private $lotes;
}
在Terrain
remove上,所有地块都将被删除。发布的第一个代码也不会删除第二个表中的数据,它只是将引用置空,如果您只依赖一个实体,通常该值永远不应为空(在该表中不应该有任何没有引用的旧行,因为在大多数情况下,您无法使用它们,它只会让该表充满您不需要的内容,并破坏索引)
从:
生命周期回调是在触发事件时调用的实体类上的方法。它们绝对不接收任何参数,并且专门设计为允许在实体类状态内进行更改。
生命周期事件侦听器是具有特定回调方法的类,这些回调方法接收某种类型的>EventArgs实例,这些实例允许访问实体、EntityManager或其他相关数据
生命周期回调仅用于更改该实体,而不是它引用的其他实体。
您必须使用生命周期事件侦听器,而不是生命周期回调。
使用生命周期事件侦听器,您可以访问实体管理器并删除这些实体。
但正确的方法是在引用上使用delete cascade,这样就可以忽略引用的对象(不必在1次操作后从数据库中读取它们来删除它们),并让数据库处理它们。
您只需更改这一行:
@ORM\JoinColumn(name="terrain_id", referencedColumnName="id")
对此
@ORM\JoinColumn(name="terrain_id", referencedColumnName="id", onDelete="cascade")
您可以在JoinColumn注释上找到文档
您可以使用cascade=“remove”建议使用OneToMany注释上的参数,但速度要慢得多。为什么不使用PostRemove而不是PreRemove?这种方法可以在地块后删除地形,而不会违反数据库完整性。删除地块后,现在可以安全地删除相关地形
/**
* @ORM\PostRemove
*/
public function deleteTerrain(\Doctrine\ORM\Event\LifecycleEventArgs $args)
{
$em = $args->getEntityManager();
$terrain = $this->getTerrain();
$em->remove($terrain);
$em->flush();
}
我知道注释中的oroperty级联,但我正在尝试用生命周期调用backshot来解决这一问题,这就是为什么我在第一个代码中解释了如何在没有级联注释的情况下正确删除批次。您尝试过吗?
@ORM\JoinColumn(name="terrain_id", referencedColumnName="id", onDelete="cascade")
/**
* @ORM\PostRemove
*/
public function deleteTerrain(\Doctrine\ORM\Event\LifecycleEventArgs $args)
{
$em = $args->getEntityManager();
$terrain = $this->getTerrain();
$em->remove($terrain);
$em->flush();
}