Tinkerwell 4 is out now! Get the most popular PHP Scratchpad application. Learn more

Go back to Blog

A guide to soft-delete models in Laravel

Sebastian Schlein

It's common that a user in your applications makes mistakes and deletes data by accident – even if you show them countless warnings before they delete the record from your database. In other scenarios you can introduce the concept of a trash that your users know from their desktop and delete trashed records after a while.

The feature that you are looking for is soft-deleting in Laravel. You can simply add a new database column to your Laravel Model and use the SoftDeletes trait on your model. After that,you are good to go and soft deletes work instantly.

Let's assume that you want to keep users for a while after they deleted their account so that you are able to restore them. Add soft delete to the User model with a new column in the up() method of a new migration:

Schema::table('users', function (Blueprint $table) {
    $table->softDeletes();
});

Add the SoftDeletes trait to the User model:

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, SoftDeletes;
 
    //...
}

That's it. From now on, your application doesn't delete Users from the database anymore when you run the delete method on a user but sets a date when this user got deleted. If this is date is set, you can use Eloquent queries like you did before and these models are ignored – this is what soft deleting is. Excluding them from normal queries where you don't ask for them explicitly.

Fire up Tinkerwell (or use php artisan tinker) for testing.

Let's create some new users via the User Factory:

User::factory()->times(5)->create();

If this is an empty project, these users should be in the database right now. You can check this with via Tinker and Eloquent easily:

User::count() // returns 5

Delete the first user:

User::first()->delete();

When you run the count query above again (Tinkerwell has a history and allows you to go back to your previous code runs easily), it only returns 4 users as if the record was deleted from the database entirely.

If you want to access deleted models, you can use the withTrashed method of Eloquent:

User::withTrashed()->count(); // returns 5 again

Restoring a soft deleted model is pretty easy too:

User::withTrashed()->where('id', 1)->restore();

This sets the deleted_at column back to NULL and makes it accessible again.

Permanently deleting models is not only useful sometimes, but also required if you work with personal data. You can permanently delete a record from the database with the forceDelete method.

User::first()->forceDelete();

If you want to clean up your database regularly and delete soft deleted models automatically, this is called pruning. Similar to adding soft-delete to a model in Laravel, you use the Prunable trait and implement a prunable method in your model that tells Laravel when you want to delete a soft-deleted model.

Add the trait:

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, SoftDeletes, Prunable;
 
    //...
}

This trait tells Laravel that it should look for the prunable method in this model when the scheduler is run.

It is a good practise to delete users after a week so that you have the option to restore them even if your support queue is full but also gives them a reasonable time until their data is wiped from your system.

public function prunable()
{
  return static::where('created_at', '<=', now()->subWeek());
}

Once this is set up, you can schedule the command to prune models daily by adding the command to your console kernel:

$schedule->command('model:prune')->daily();

That's soft delete in Laravel.

While you are here, take a look at this app for Laravel developers like you: Tinkerwell

Tinkerwell: The PHP Scratchpad

Enjoy coding and debugging in an editor designed for fast feedback and quick iterations. It's like a shell for your application – but with multi-line editing, code completion, and more.