在 Laravel 中软删除父记录时如何软删除相关记录?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32163509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to soft delete related records when soft deleting a parent record in Laravel?
提问by user3407278
I have this invoices table that which has the following structure
我有这个发票表,它具有以下结构
id | name | amount | deleted_at
2 iMac 1500 | NULL
and a payments table with the following structure
和具有以下结构的支付表
id | invoice_id | amount | deleted_at
2 2 1000 | NULL
Invoice Model
发票模型
class Invoice extends Model {
use SoftDeletes;
}
here's the code to delete the invoice
这是删除发票的代码
public function cance(Request $request,$id)
{
$record = Invoice::findOrFail($id);
$record->delete();
return response()->json([
'success' => 'OK',
]);
}
Payments model
支付模式
class Payment extends Model {
use SoftDeletes;
}
The softDelete on Invoice table works perfectly but its related records (payments) still exists.How do I delete them using softDelete?
Invoice 表上的 softDelete 工作正常,但其相关记录(付款)仍然存在。如何使用 softDelete 删除它们?
回答by jedrzej.kurylo
Eloquentdoesn't provide automated deletion of related objects, therefore you'll need to write some code yourself. Luckily, it's pretty simple.
Eloquent不提供自动删除相关对象的功能,因此您需要自己编写一些代码。幸运的是,这很简单。
Eloquent modelsfire different events in different stages of model's life-cycle like creating, created, deleting, deleted etc. - you can read more about it here: http://laravel.com/docs/5.1/eloquent#events. What you need is a listener that will run when deletedevent is fired - this listener should then delete all related objects.
Eloquent 模型在模型生命周期的不同阶段触发不同的事件,例如创建、创建、删除、删除等 - 您可以在此处阅读更多相关信息:http: //laravel.com/docs/5.1/eloquent#events。您需要的是一个在删除事件被触发时运行的监听器——然后这个监听器应该删除所有相关的对象。
You can register model listeners in your model's boot()method. The listener should iterate through all payments for the invoice being deleted and should delete them one by one. Bulk delete won't work here as it would execute SQL query directly bypassing model events.
您可以在模型的boot()方法中注册模型侦听器。侦听器应遍历要删除的发票的所有付款,并应将它们一一删除。批量删除在这里不起作用,因为它会直接绕过模型事件执行 SQL 查询。
This will do the trick:
这将解决问题:
class MyModel extends Model {
protected static function boot() {
parent::boot();
static::deleted(function ($invoice) {
$invoice->payments()->delete();
});
}
}
回答by Rwd
You can go one of 2 ways with this.
您可以采用以下两种方式之一。
The simplest way would be to override Eloquents delete()
method and include the related models as well e.g.:
最简单的方法是覆盖 Eloquentsdelete()
方法并包含相关模型,例如:
public function delete()
{
$this->payments()->delete();
return parent::delete();
}
The above method should work just find but it seems a little bit dirty and I'd say it's not the preferred method within the community.
上面的方法应该可以找到,但它似乎有点脏,我想说这不是社区内的首选方法。
The cleaner way (IMO) would be to tap into Eloquents events e.g.:
更简洁的方法(IMO)是利用 Eloquents 事件,例如:
public static function boot()
{
parent::boot();
static::deleting(function($invoice) {
$invoice->payments()->delete();
});
}
Either (but not both) of the above methods would go in your Invoice
model.
Also, I'm assuming that you have your relationships set up in your model, however, I'm not sure if you allow multiple payments for one invoice. Either way you might need to change the payments()
in the examples to whatever you've named the relationship in your invoice model.
上述方法中的任何一种(但不是两种)都可以用于您的Invoice
模型。另外,我假设您在模型中建立了关系,但是,我不确定您是否允许对一张发票进行多次付款。无论哪种方式,您都可能需要payments()
将示例中的更改为您在发票模型中命名的任何关系。
Hope this helps!
希望这可以帮助!
回答by Salar Bahador
I know you asked this question a long time ago but I found this packageto be very simple and straightforward.
我知道你很久以前就问过这个问题,但我发现这个包非常简单明了。
Or you can use this packageit's useful too.
或者你可以使用这个包,它也很有用。
Rememberto install the right version depending on your laravel version.
请记住根据您的 Laravel 版本安装正确的版本。
You must install it via composer:
您必须通过 composer 安装它:
composer require askedio/laravel5-soft-cascade ^version
In second package:
在第二个包中:
composer require iatstuti/laravel-cascade-soft-deletes
Register the service provider in your config/app.php.
在 config/app.php 中注册服务提供者。
you can read the docs on the GitHub page.
您可以阅读 GitHub 页面上的文档。
If you delete a record this package recognizes all of its children and soft-delete them as well.
如果您删除一条记录,此包会识别其所有子项并软删除它们。
If you have another relationship in your child model use its trait in that model as well. its so much easier than doing it manually.
如果您的子模型中有另一个关系,则在该模型中也使用其特征。它比手动完成要容易得多。
The second package has the benefit of deleting grandchildren of the model. in some cases, I say its a better approach.
第二个包的好处是删除模型的孙子。在某些情况下,我说这是一种更好的方法。
回答by Waiyl Karim
If the relationship of your database does not go any further than only one layer,then you could simply use Laravel events to handle your soft-deletes within the Model boot()
method as follow:
如果您的数据库关系不只是一层,那么您可以简单地使用 Laravel 事件来处理 Modelboot()
方法中的软删除,如下所示:
<?php
//...
protected static boot() {
parent::boot();
static::deleting(function($invoice) {
$invoice->payments()->delete();
});
}
If, however, your structure goes deeper than only one layer, you will have to tweak that piece of code.
但是,如果您的结构比只有一层更深,您将不得不调整那段代码。
Let's say for example you don't want to remove the payments of an invoice but rather the whole payment history of a given user.
例如,假设您不想删除发票的付款,而是要删除给定用户的整个付款历史记录。
<?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);
}
}
This paradigm ensures Laravel to follow the rabbit hole no matter how deep it goes.
这种范式确保 Laravel 能够跟随兔子洞,无论它有多深。