Cascading SoftDeletes with Laravel 5

Will Bowman
asked.io
Published in
2 min readOct 1, 2017

Laravels Soft Deleting allows you to retain deleted records in your database so they can be used or restored at a later point. Restoring deleted records is great if a mistake is made and you need to revert and retaining deleted data can often be useful in the event you need to pull up some old records.

TL:DR: Take me to the package!

Traditionally Deleting Relations

I’ve always used MySQL foreign key constraints to cascade delete related records. Laravel makes it easy to use foreign keys in migrations, set `onDelete` to cascade and walla, your relations will be deleted automatically.

But what happens when you enable SoftDeletes? Your database is never told to actually ‘delete’ a record, instead the `deleted_at` field is updated. So what happens to your cascading deletes? Nothing, your related records are left alone.

Cascading Soft Deletes

Since soft deletes don’t actually delete any records we need some way to cascade, or iterate over each, related model.

If you google “laravel 5 cascade soft delete” you’ll find a lot of different options.

While each option may be different they all pretty much work the same way, you define the relations when deleting.

You do it in a model like this example:

public static function boot()
{
parent::boot();
// cause a delete of a product to cascade to children so they are also deleted
static::deleted(function($product)
{
$product->images()->delete();
$product->descriptions()->delete();
});
}

Or even better, as an Event like here:

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

There is another way

Both options require us to duplicate a lot of code. Option 1 even requires us to override the boot function.

They both require us to define these settings for each Model, that’s quite a bit of code — and almost all of it will be duplicated minus the actual relations.

My solution was to use Events and an array in the Model to tell it what to cascade, this allows us to simply add 2 lines to a Model to enable cascade deleting and restoring:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class User extends Model
{
use \Illuminate\Database\Eloquent\SoftDeletes;
use \Askedio\SoftCascade\Traits\SoftCascadeTrait;
protected $fillable = ['name', 'email', 'password']; protected $softCascade = ['profiles']; public function profiles()
{
return $this->hasMany('App\Profiles');
}
}

We needed to add the trait to enable the ability to read the `protected $softCascade` variable.

use \Askedio\SoftCascade\Traits\SoftCascadeTrait;

Then we we define `$softCascade` with the array of relations we want to cascade delete.

protected $softCascade = ['profiles'];

Each model gets its own array, if the array is empty or doesn’t exist that models relations wont be deleted.

--

--