Cascading SoftDeletes with Laravel 5

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

Use the Laravel 5 SoftCascade Package I created to easily enable cascading soft delete and restore.

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 wallah, 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 models.

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();
  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’s a better 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:

<?php

namespace 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.

Conclusion

Cascade deleting is awesome, it makes dealing with relations much easier. Enabling soft deletes is cool, but it screws up your cascading — Laravel doesn’t help with this and all the google search results are fairly poor.

Duplicating code or manually defining relations on delete is such a pain, I wanted an easy way to cascade soft deletes and what’s easier then defining an array? Very little.

We already define arrays of data for $fillable and $hidden, so adding another array is nothing new, it’s easy to understand, follow, and use.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.