Laravel 5: 级联软删除

35

我有一个包含offersservices的表格。

Service(s)offer的子项。到目前为止,我已经实现了软删除offer的功能。如何也软删除服务?这是我的代码:

迁移Offers

Schema::create('offers', function(Blueprint $table)
{
    $table->increments('id')->unsigned();
    ...    
    $table->timestamps();
    $table->softDeletes();
});

迁移服务

Schema::create('services', function(Blueprint $table) 
{
    $table->increments('id');
    $table->integer('offer_id')->unsigned();   
    ...
    $table->timestamps();
    $table->softDeletes();
});

Schema::table('services', function($table) 
{
    $table->foreign('offer_id')
          ->references('id')
          ->on('offers');
});

模型优惠

use SoftDeletes;
protected $dates = ['deleted_at'];

public function services() {
    return $this->hasMany('App\Service');
} 

模型服务

public function offer() {
    return $this->belongsTo('App\Offer');
} 

删除方法

public function destroy($id)
{
    $offer = Offer::find($id);
    $offer->delete();
}

谢谢您的所有帮助。

4个回答

51
我已经将这段代码放入了Offer模型中:
protected static function boot() {
    parent::boot();

    static::deleting(function($offer) {
        $offer->services()->delete();
    });
}

并添加了缺失的

use SoftDeletes;
protected $dates = ['deleted_at'];

在服务模型中。


3
但是如果服务本身有外键,这种解决方案就不适用了... 在子模型中删除操作不会被触发。 - Juliatzin
我一直在为这个问题苦苦思索,不知道为什么它对我不起作用。后来发现,这是因为当直接对查询进行删除调用时,它不会调用“deleting”和“deleted”方法。 以下是更多详细信息和如何使其工作的示例:https://github.com/laravel/framework/issues/2536#issuecomment-74557441 - Arno van Oordt
当你需要级联访问几个层级(从祖父到孩子)时,你必须通过foreach加载模型,如此处所述:https://github.com/laravel/framework/issues/2536#issuecomment-101330841 - DumbergerL

7
您应该使用 Eloquent 事件 来实现此目的。
Offers::deleted(function($offer) {
    $offer->services()->delete();
});

Offers::restored(function($offer) {
    $offer->services()->withTrashed()->restore();
});

1
非常感谢您的努力。我已经尝试将这段代码放在我的删除方法底部,但服务仍然存在于数据库中。我需要自己编写一些内容吗? - be-codified
1
有人回复吗?谢谢。 - be-codified

5

如果您想在Eloquent模型中使用级联软删除功能,我强烈推荐使用这个库: iatstuti/laravel-cascade-soft-deletes

Composer

// get it with composer.
$ composer require iatstuti/laravel-cascade-soft-deletes="1.0.*"

快速示例

这个示例源自入门样例。

<?php

namespace App;

use App\Comment;
use Iatstuti\Database\Support\CascadeSoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes, CascadeSoftDeletes;

    protected $cascadeDeletes = ['comments'];

    protected $dates = ['deleted_at'];

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}  

2
你可以这样做。
self::deleting(function($offer) {
    $offer->services()->delete();
});

self::restoring(function ($offer) {
   $offer->services()->restore();
});

在删除/恢复父对象(offer)之前,您应该先删除/恢复子记录(services)。如果没有这样做,会触发引用完整性MySql错误。请注意保留HTML标记。

4
由于记录只是软删除,所以它无法触发完整性错误。但是,在恢复子项之前,您需要先恢复父项。因此,请使用self::restored - halloei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接