我有这张发票表,它具有以下结构
id | name | amount | deleted_at
2 iMac 1500 | NULL
以及具有以下结构的付款表
id | invoice_id | amount | deleted_at
2 2 1000 | NULL
发票模型
class Invoice extends Model {
use SoftDeletes;
}
这里是删除发票的代码
public function cance(Request $request,$id)
{
$record = Invoice::findOrFail($id);
$record->delete();
return response()->json([
'success' => 'OK',
]);
}
付款模式
class Payment extends Model {
use SoftDeletes;
}
Invoice表上的softDelete工作正常,但其相关记录(付款)仍然存在。如何使用softDelete删除它们?
答案 0 :(得分:14)
Eloquent 并不能自动删除相关对象,因此您需要自己编写一些代码。幸运的是,它非常简单。
雄辩的模型在模特的生命周期的不同阶段发布不同的事件,如创建,创建,删除,删除等等。您可以在此处阅读更多相关信息:{{3} }。你需要的是一个在删除事件被触发时运行的监听器 - 这个监听器应该删除所有相关的对象。
您可以在模型的 boot()方法中注册模型侦听器。监听器应该迭代所有要删除的发票的付款,并且应该逐个删除它们。批量删除不会在这里工作,因为它将直接绕过模型事件执行SQL查询。
这样可以解决问题:
class MyModel extends Model {
protected static function boot() {
parent::boot();
static::deleted(function ($invoice) {
$invoice->payments()->delete();
});
}
}
答案 1 :(得分:9)
您可以使用以下两种方法之一。
最简单的方法是覆盖Eloquents delete()
方法并包括相关模型,例如:
public function delete()
{
$this->payments()->delete();
return parent::delete();
}
上述方法应该可以找到,但看起来有点脏,我说它不是社区中首选的方法。
更清洁的方式(IMO)将利用Eloquents事件,例如:
public static function boot()
{
parent::boot();
static::deleting(function($invoice) {
$invoice->payments()->delete();
});
}
上述方法中的任何一个(但不是两个)都会进入Invoice
模型。
另外,我假设您在模型中设置了关系,但是,我不确定您是否允许为一张发票支付多笔款项。无论哪种方式,您都可能需要将示例中的payments()
更改为您在发票模型中命名关系的任何内容。
希望这有帮助!
答案 2 :(得分:8)
我知道你很久以前就问了这个问题,但我发现this package非常简单明了。
或者您可以使用this package它也很有用。
请记住根据您的laravel版本安装正确的版本。
您必须通过composer安装它:
composer require askedio/laravel5-soft-cascade ^version
在第二个包中:
composer require iatstuti/laravel-cascade-soft-deletes
在config / app.php中注册服务提供商。
您可以在GitHub页面上阅读文档。
如果你删除了一个记录,这个包可以识别它的所有子节点,也可以软删除它们。
如果您的孩子模型中有另一种关系,也要在该模型中使用其特征。它比手动操作容易得多。
第二个包的好处是删除模型的孙子。在某些情况下,我说它是一种更好的方法。
答案 3 :(得分:0)
如果您的数据库关系不仅仅局限于一层,,那么您可以简单地使用Laravel事件在Model boot()
方法内处理软删除,如下所示:
<?php
//...
protected static boot() {
parent::boot();
static::deleting(function($invoice) {
$invoice->payments()->delete();
});
}
但是,如果您的结构仅比一层更深,那么您将不得不调整这段代码。
例如,您不想删除发票的付款,而是要删除给定用户的全部付款历史记录。
<?php
// ...
class Invoice extends Model
{
// ...
/**
* Holds the methods names of Eloquent Relations
* to fall on delete cascade or on restoring
*
* @var array
*/
protected static $relations_to_cascade = ['payments'];
protected static boot()
{
parent::boot();
static::deleting(function($resource) {
foreach (static::$relations_to_cascade as $relation) {
foreach ($resource->{$relation}()->get() as $item) {
$item->delete();
}
}
});
static::restoring(function($resource) {
foreach (static::$relations_to_cascade as $relation) {
foreach ($resource->{$relation}()->get() as $item) {
$item->withTrashed()->restore();
}
}
});
}
public function payments()
{
return $this->hasMany(Payment::class);
}
}
<?php
// ...
class User extends Model
{
// ...
/**
* Holds the methods names of Eloquent Relations
* to fall on delete cascade or on restoring
*
* @var array
*/
protected static $relations_to_cascade = ['invoices'];
protected static boot()
{
parent::boot();
static::deleting(function($resource) {
foreach (static::$relations_to_cascade as $relation) {
foreach ($resource->{$relation}()->get() as $item) {
$item->delete();
}
}
});
static::restoring(function($resource) {
foreach (static::$relations_to_cascade as $relation) {
foreach ($resource->{$relation}()->get() as $item) {
$item->withTrashed()->restore();
}
}
});
}
public function invoices()
{
return $this->hasMany(Invoice::class);
}
}
这种范例可确保Laravel不管其深度有多深都可以跟随兔子的洞。