Working With Soft Deletes in Laravel 8 and 9 (By Example)
https://www.thisprogrammingthing.com/2020/Working-With-Laravels-SoftDelete-Trait/
Working With Soft Deletes in Laravel 8 and 9 (By Example)
Last Updated: Jan 11, 2022

The annoying thing about deleting data from a database is that it’s gone forever. We can’t even look at the data to see if we needed it because it’s gone. If we need the data back, our only solution will be to restore a backup and hope we have the backup just before it was deleted so the loss is minimized.
Thankfully, Laravel provides a built-in feature that allows us to flag database rows as deleted without actually deleting them from the database. This article/video discusses how to use Soft Deletes in Laravel.
Why Should We Use Soft Deletes?
As we’ve discussed in “Stop Deleting Data”, when we DELETE a row from the database it’s gone forever without going through a potentially painful process of doing a full database restore. Soft deleting the data allows us to easily view and restore the data with minimal work and can be a huge time saver when data is accidentally deleted.
Laravel provides support for soft deleting using the Illuminate\Database\Eloquent\SoftDeletes trait.
Migrations
The first part of the process we need to tackle is setting up our database tables to have the SoftDeletes column.
Adding the Soft Delete Columns to a New Table
Let’s start by creating a new model to track a Project in a project management application. We’ll create the model and migration in one step so we can be as lazy as possible.
$ php artisan make:model -m Project
Model created successfully.
Created Migration: 2020_05_02_012758_create_projects_tableWhen we open the newly created migration we’ll add the following lines to our up() function.
It looks like this.
The $table->softDeletes(); function call is what sets up the table to allow for the SoftDeletes trait to work. Without it, we’ll get query errors.
Now we’ll run the migration.
Let’s look at what the table looks like inside MySQL.
As we can see there’s a deleted_at column in the table definition. This is what the $table->softDeletes(); call added to the table and what the SoftDeletes trait will use to track if the row has been deleted.
Adding the Soft Delete Columns to an Existing Table
Let’s look at how we can add the soft delete columns to an existing table. We’re going to create a new migration using the make:migration command to add the columns to the users table because out of the box Laravel doesn’t have this column on the users table.
Next we’re going to alter the migration so it both adds the columns in the up() function ($table->softDeletes();) and removes them in the down() function ($table->dropSoftDeletes();).
Again, we’ll run the migration.
Setting Up the Model to Use Soft Deletes
Now that we have our database tables set up we can start working with soft deleted models in our code. The first step is adding the Illuminate\Database\Eloquent\SoftDeletes trait to the models. Below is an example model where we have set it up to use the SoftDeletes logic.
It’s important to note that even though we added the SoftDeletes column to our model Laravel doesn’t automatically use it until we add the trait so we will still irreparably delete data without it.
Deleting a Model
Now that everything is set up let’s test it to see what happens.
First we’ll use tinker to create a new Project.
When we check the database we can see that it’s been persisted to the database and the deleted_at column is set to null indicating that it hasn’t been deleted.
Now we’ll delete the model.
And back in MySQL, we can see deleted_at is no longer null which indicates it has been deleted.
Restoring a Model
If we accidentally delete the model Laravel makes it easy to restore the record using the restore() function.
Deleting a Model
Let’s say you have a case where someone accidentally entered information and we need to delete the record from the database and not just mark it as deleted. SoftDeletes provides the forceDelete() function that will do just that.
Finding a Deleted Model
What happens when we delete a model and need to find it later?
First, let’s set up a new Project and soft delete it.
When we attempt to use findOrFail() we’ll receive a ModelNotFoundException because the SoftDeletes trait is filtering them out.
To get around this we need to call the withTrashed() function before we call findOrFail().
Finding a Deleted Model In a Relationship
The other part of our code we need to be on the lookout for is when we have a model that defines an Eloquent relationship with the SoftDeletes models.
Normally, we would define our relationship like so.
If the User associated with this Project is soft-deleted and we attempt to access it through this relationship the function will return null.
The solution to this again is to use the withTrashed() function to have it return a result.
Viewing Trashed Models From a Controller
One of the annoying parts about the soft delete trait is that if a user attempts to access a page for a deleted resource they’ll receive a 404 error and not something helpful like a message informing them the item was deleted. To get around this we can add a call to withTrashed() to our route definition.
Adding deleted_by
deleted_byAs a small aside, one of the things we like to do is also track who deleted the model. This is helpful because then not only can we tell people when an entity was deleted but can also tell them who did it. It makes it so much easier to track down why it was deleted it if wasn’t supposed to be.
We do this by adding a deleted_by column and then we create our own delete() function that sets both the deleted_at and deleted_by columns to the correct values and saves the results.
We generally add this to our own SoftDeletes trait or class.
What You Need To Know
Soft deletes allow us to keep data in the database
Makes it easier to restore
Makes it easier to see when it was deleted
Looking for a new Laravel Developer Job? You can find one with one click using Jooble.
Last updated
Was this helpful?