如何在Laravel4中进行软删除层叠?

11 浏览
0 Comments

如何在Laravel4中进行软删除层叠?

尝试使用带有级联删除和软删除的外键,但运气不太好。

我有两个表:Users(用户)和Events(事件)。这两个表都有软删除功能。

用户可以拥有0到n个事件。

事件有一个user_id,作为对用户的外键,如下所示:

$table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE');

问题是,当我删除一个用户时,它会被软删除,但它的事件不会被软删除或物理删除。

我是做错了什么吗,还是这是正确的Eloquent行为?

其次,如果这是正确的行为,如何最好地实现级联删除?也许可以像这样覆盖我的模型中的delete()方法...

public function delete()
{
  //删除所有事件...
  __parent::delete()
}

0
0 Comments

问题的原因是数据库的外键不会自动级联删除,只有在更新或删除主键时,相关的行才会被修改。

根据我找到的关于这个主题的所有信息,解决方法是使用Eloquent的模型事件来监听删除事件,并更新相关的表。

另一种方法是“扩展”delete()方法,并直接包含相应的功能。

Cryode,我尝试了模型事件,它可以部分地工作。让我解释一下。真实的情况是有3个表:Users、Events和Comments。Events拥有0到n个Comments。按照链接中的说明,我在Users和Events的boot()方法中添加了逻辑。现在:软删除Event,预期:软删除Comments,结果:OK;软删除User,预期:软删除Events,结果:OK;软删除与这些事件相关的Comments,结果:KO。似乎删除在第一个“级别”之外不会传播。

这是我自己实施的解决方案。我首先绘制出所有我的模型之间的关系图,然后在我的模型中编写扩展Eloquent的删除方法,以实现级联删除。最后,由于这是一个容易出错的任务,我编写单元测试来展示级联效果只影响应该影响的部分。

文章整理如下:

Laravel4中如何在软删除时进行级联删除?

问题的原因是数据库的外键不会自动级联删除,只有在更新或删除主键时,相关的行才会被修改。根据我找到的关于这个主题的所有信息,解决方法是使用Eloquent的模型事件来监听删除事件,并更新相关的表。另一种方法是“扩展”delete()方法,并直接包含相应的功能。

Cryode,我尝试了模型事件,它可以部分地工作。让我解释一下。真实的情况是有3个表:Users、Events和Comments。Events拥有0到n个Comments。按照链接中的说明,我在Users和Events的boot()方法中添加了逻辑。现在:软删除Event,预期:软删除Comments,结果:OK;软删除User,预期:软删除Events,结果:OK;软删除与这些事件相关的Comments,结果:KO。似乎删除在第一个“级别”之外不会传播。

这是我自己实施的解决方案。我首先绘制出所有我的模型之间的关系图,然后在我的模型中编写扩展Eloquent的删除方法,以实现级联删除。最后,由于这是一个容易出错的任务,我编写单元测试来展示级联效果只影响应该影响的部分。

0
0 Comments

问题的原因是在Laravel4中,当使用软删除(SoftDeletes)功能时,如果一个模型有关联的子模型(例如:用户模型和事件模型),在删除用户模型时,子模型不会自动删除,需要手动处理。

解决方法有以下几种:

1. 在删除用户模型之前,手动删除关联的子模型(事件模型):

$user->events()->delete();
$user->delete();

2. 在用户模型中创建自定义的删除方法:

public function customDelete(){
    $this->events()->delete();
    return $this->delete();
}

3. 可以使用模型观察器(Model Observers)来监听删除事件,但在上述场景中,前两种方法更为简单。

http://laravel.com/docs/4.2/eloquent#model-observers

0
0 Comments

问题的出现原因:

尝试使用ON UPDATE CASCADE来级联软删除在两个表中是不正确的方法。这是因为需要创建一个外键到复合键的关系。也就是说,需要将(events.user_id和deleted_at)与(user.id和deleted_at)进行关联。当你更改其中一个时,它会更新另一个。

解决方法:

首先,需要在删除的列中添加一个默认规则,因为不能在空值上进行链接。

所以在两个表的迁移中添加以下代码:

$table->softDeletes()->default('0000-00-00 00:00:00');

在用户表中添加一个使用'id'和'deleted_at'的唯一键:

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

然后在事件表中创建一个外键(链接到唯一键):

Schema::table('events', function($table) { 
    $table->foreign(array('user_id','deleted_at'),'events_deleted_at_foreign_key')
        ->references(array('id','deleted_at'))->on('users')->onUpdate('CASCADE');
});

这样运行后,如果你软删除用户,它将软删除其事件。

然而,如果你现在尝试软删除事件,它将在外键约束上失败。为什么呢?

因为你正在创建一个使用id和deleted_at在两个表中的父子关系。更新父项将更新子项,并且关系不会中断。然而,如果你更新子项,关系现在就中断了,导致子项在表中成为孤立项。这违反了外键约束。

因此,要么使用TRIGGERS来处理你尝试做的事情,要么在你的应用程序中处理它。个人建议使用TRIGGERS,这样数据库保持独立实体,不需要依赖任何东西来保持数据完整性。

0