If you want to delete a model with related models you can use Laravel model events. There is also a special case if your models cascade.
Lets say you have Folder and File Eloquent models that are related and use SoftDeletes trait and when you delete a folder you also want to delete files in folder and all subfolders with files.
In the boot
method or Folder model you catch delete
and restore
events (actually deleting
and restoring
events that trigger before restoring or deleting happens). You can delete/restore all files in folder you're deleting/restoring with $folder->files()->delete();
and $folder->files()->withTrashed()->restore();
.
Folders on the other hand cascade (folder in a folder in a folder) and because events do not trigger if you don't pull the models (->get()
method), the model events won't trigger for subfolders. That's why you need to pull the folders and iterate trough them (->each()
method) and delete/restore them.
You could use database CASCADE feature but that does not work with soft deletes.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\File;
class Folder extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
public function files()
{
return $this->hasMany(File::class);
}
public function subfolders()
{
return $this->hasMany(Folder::class, 'parent_id');
}
public static function boot()
{
parent::boot();
// cause a delete of a folder to cascade
// to children so they are also deleted
static::deleting(function($folder) {
if ($folder->forceDeleting) {
$folder->subfolders()->withTrashed()->get()
->each(function($subfolder) {
$subfolder->forceDelete();
});
$folder->files()->withTrashed()->forceDelete();
} else {
$folder->subfolders()->get()
->each(function($subfolder) {
$subfolder->delete();
});
$folder->files()->delete();
}
});
// cause a restore of a folder to cascade
// to children so they are also restored
static::restoring(function($folder) {
$folder->subfolders()->withTrashed()->get()
->each(function($subfolder) {
$subfolder->restore();
});
$folder->files()->withTrashed()->restore();
});
}
}