如何在Laravel4中级联软删除?

如何在Laravel4中级联软删除?,laravel,laravel-4,eloquent,cascading-deletes,Laravel,Laravel 4,Eloquent,Cascading Deletes,尝试使用带有delete cascade和softDeletes的外键,但运气不佳 我有两个表:用户、事件。两个表都有软删除 用户可以有0..n个事件。 事件有一个用户id,用作用户的外键,如下所示: $table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE'); 问题是,当我删除一个用户时,它会被软删除,但它的事件不会被软删除

尝试使用带有delete cascade和softDeletes的外键,但运气不佳

我有两个表:用户、事件。两个表都有软删除

用户可以有0..n个事件。
事件有一个用户id,用作用户的外键,如下所示:

$table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE');
问题是,当我删除一个用户时,它会被软删除,但它的事件不会被软删除或物理删除

我是做错了什么,还是这是正确的雄辩行为

其次,如果这是正确的行为,如何最好地实现删除级联?可能在我的模型中重写delete()方法,如下所示

public function delete()
{
  //delete all events...
  __parent::delete()
}

数据库的外键不会起任何作用,因为您没有更改主键。只有更新或删除主键,相关行才会被修改

从我能找到的关于这个主题的所有信息来看,解决方案是使用Eloquent来侦听删除事件,并更新相关表


或者,您可以“扩展”
delete()
方法,并直接包含该功能

如果我理解正确,您正在尝试在两个表中级联软删除

我相信用更新级联来实现这一点不是正确的方法。我会尽力解释为什么

要尝试这样做,您需要创建一个外键到复合键的关系

ie您需要将(events.user_id和deleted_at)链接到(user.id和delete_at)。你改变一个,它会更新另一个

首先,您需要向已删除的_at列添加默认规则,因为您不能链接空值

因此,将这两个表添加到迁移中。。。
$table->softDeletes()->默认值('0000-00-00:00:00')

使用“id”和“deleted_at”将唯一键添加到用户表中

Schema::table('users;function($table){
$table->unique(数组('id','deleted_at'))
});

然后在events表中创建一个类似于这样的外键(指向唯一键的链接)

Schema::table('events;function($table){
$table->foreign(数组('user\u id','deleted\u at'),'events\u deleted\u at\u foreign\u key')->
}->引用(数组('id','deleted_at'))->on('users')->onUpdate('CASCADE')

运行此命令,您现在应该会发现,如果您软删除您的用户,它将软删除其“事件”

但是,如果您现在尝试软删除事件,它将在外键约束上失败。你为什么会问

您要做的是使用两个表中的id,deleted\u创建父子关系。更新父项将更新子项。而且这种关系没有中断。但是,如果更新子级,则关系现在将断开,使子级在表中成为孤立项。这使外键约束失效

这是一个冗长的答案,但希望能很好地解释为什么你试图做的事情不起作用,并为你节省大量的时间。要么进入触发器,并触发一个函数来处理您试图执行的操作,要么在应用程序中处理它。就我个人而言,我会使用触发器,这样数据库就可以保持它自己的实体,而不必依赖任何东西来保持数据的完整性

delimiter //
为每行在db.users上更新后创建触发器软\u删除\u子项 开始 如果NEW.deleted_at OLD.deleted_at THEN 更新事件集deleted_at=NEW.deleted_at WHERE events.user_id=NEW.id; 如果结束; 结束

//
定界符

你想得太多了

在删除用户之前删除事件:

$user->events()->delete();
$user->delete();
或在用户模型中创建客户删除功能:

public function customDelete(){
    $this->events()->delete();
    return $this->delete();
}
您还可以添加一个模型观察者并观察deleting或delete事件,但是在上面提到的场景中,前两种方法将是一个更简单的解决方案


Cryode,我尝试了模型事件,但部分有效。让我解释一下。实际情况是3个表:用户、事件、注释。事件有0..n个注释。接下来,我在boot()方法中为用户和事件添加了逻辑。现在:softDelete事件,预期:softDelete注释,结果:OK;softDelete用户,应为:softDelete事件,结果:OK,对这些事件的softDelete注释,结果:KO。似乎删除不会传播到第一个“级别”之外。这是我自己实现的解决方案。我首先画出所有模型之间的关系图,然后编写delete方法,在我的模型中扩展elount,它应该级联删除。最后,由于这是一项容易出错的任务,我编写了单元测试,以表明级联效应只会影响到它可能产生的结果。这种方式,用户删除调用UserRecords delete,然后调用UserRecords数据删除,依此类推。