How to Use Soft Deletes in Laravel? (A Tactic for Data Safety)

author
Mayur Upadhyay

Quick Summary

Laravel’s soft deletes provide a crucial data safety net. Instead of permanently removing records, they are marked as deleted with a timestamp, making them invisible to default queries. This allows for easy recovery of accidentally deleted data, maintains referential integrity, and enables powerful features like an admin trash bin, all with minimal setup.

A cautious developer clicks “delete” on a user record. But just moments later, they get to know the data was critical and the action was a mistake. Permanent deletion in database management can be risky. Possibly, accidental data loss, broken application relationships, etc.

But Eloquent ORM offers a built-in mechanism of soft deletes in Laravel. This pattern marks records as inactive without permanently removing them from the database. It acts as a safety net against irrecoverable errors.

This blog explores soft deletes in Laravel, ensuring robust and recoverable data workflows. You’ll learn how to use it, along with some key info. So let’s begin.

What are Soft Deletes in Laravel?

Soft delete is a way of marking a database record as deleted without actually erasing it. Instead of using a SQL DELETE statement, Laravel updates a special deleted_at column on the record with the current date and timestamp.

Think of it like moving a file to the recycle bin on your computer. The file is no longer in its original location and appears to be gone, but it still exists on your drive and can be restored if needed.

How Does Soft Deletes in Laravel Work?

Laravel’s Eloquent ORM has soft deleting functionality built-in. To use it, you simply:

  1. Add a deleted_at column to your database table (which Laravel’s migrations can handle).
  2. Use the SoftDeletes trait on the corresponding Eloquent model.

Once this is set up, every time you call the delete() method on a model, Laravel will set the deleted_at column to the current time. Subsequent queries will automatically exclude this “soft deleted” record. That makes it seem like it’s no longer there, while it remains safely stored in the database.

Why Use Soft Deletes in Laravel?

Soft deletes are a critical part of responsible data management. The primary motivation is data safety and recovery. Accidental deletions are a common occurrence, and soft deletes provide an immediate safety net. So you can restore records without relying on complex database backups.

Let’s look at a few key reasons to use soft deletes in Laravel.

Data Recovery and Restoration

This is the most significant advantage. Soft deletes act as a safety net, allowing you to easily restore users, orders, or posts that were deleted by mistake. A simple update setting the deleted_at column to NULL is all it takes to recover the record fully.

Preventing Accidental Data Loss

It protects against irreversible human error. A team member accidentally deleting a critical customer record becomes a minor inconvenience instead of a catastrophic data loss event.

Data Auditing and Change Tracking

Soft-deleted records remain in the database, providing a complete history of all entries, including when they were “removed.” This is crucial for generating accurate reports, analyzing user lifecycle, and maintaining a reliable audit trail.

Safer Data Management

By providing a buffer between intention and permanent action, soft deletes enable a more cautious and professional approach to data handling. You can confidently manage your application’s content, knowing you have a recovery option.

In essence, soft deletes shift the paradigm from permanent data destruction to reversible data archiving. It significantly reduces operational risk.

How to Use Soft Deletes in Laravel?

Implementing soft deletes in Laravel is straightforward, involving just two key steps. Eloquent handles the complex logic behind the scenes.

Step 1: Prepare the Database

Add a deleted_at column to your table via a migration. Laravel includes a helper method for this.

// In your migration file (e.g., `create_posts_table`)
public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content');
        $table->timestamps();
        // Adds the nullable `deleted_at` TIMESTAMP column
        $table->softDeletes();
    });
}

Run the migration with php artisan migrate.

Step 2: Enable Soft Deletes in the Model

In your corresponding Eloquent model, import and use the SoftDeletes trait.

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Post extends Model
{
    use HasFactory, SoftDeletes;
}

After incorporating the SoftDeletes trait, your model can efficiently manage soft deletions within your Laravel application. To understand how this feature interacts with more complex data structures, explore the concept of the Laravel Many To Many Relationship, which enables seamless data association between interconnected models.

Step 3: Soft Delete a Model

Now, when you call the delete() method on a model instance, it will set the deleted_at timestamp instead of permanently deleting the record.

$post = Post::find(1);
$post->delete(); // Performs a soft delete

Step 4: Retrieve Records (Including Trashed Models)

By default, soft-deleted models are excluded from queries. Use these methods to include them.

  • To include soft-deleted models in your results, use withTrashed().
  • To retrieve only soft-deleted models, use onlyTrashed().
// Get ALL posts, including soft-deleted ones
$allPosts = Post::withTrashed()->get();
// Get ONLY soft-deleted posts
$trashedPosts = Post::onlyTrashed()->get();

Step 5: Recover or Restore Soft Deleted Records

To restore a soft-deleted model, use the restore() method on a trashed instance.

// Find a specific trashed post and restore it
$post = Post::withTrashed()->where('id', 1)->first();
$post->restore();
// Or restore all trashed posts
Post::onlyTrashed()->restore();

Step 6: Permanently Delete Records

To permanently remove a soft-deleted model from the database, use the forceDelete() method. This is a true, irreversible deletion.

$trashedPost->forceDelete(); // Permanently removes the record from the database

Want help with execution of this procedure for database management? Then partner up with a Laravel development company.

Handling Route Model Binding with Soft Deletes in Laravel

By default, Laravel’s route model binding will not find models that have been soft deleted. This is a safety feature, as it prevents your application from accidentally displaying “deleted” content at a public URL.

However, you often need to access these trashed records in an admin panel for review or restoration. To handle this, Laravel provides a dedicated method for binding trashed models.

Using withTrashed in Route Binding

You can instruct Laravel’s implicit binding to include soft-deleted models by using the withTrashed scope in your route definition.

// In your routes file (e.g., web.php)
Route::get('/posts/{post}', function (Post $post) {
    // This will return a 404 if the post is soft-deleted.
})->name('posts.show');
// To include trashed posts, define the binding like this:
Route::get('/admin/posts/{post}', function (Post $post) {
    // This will find the post even if it's soft-deleted.
})->withTrashed();

A Practical Example: Admin Restoration Flow

This is particularly useful for an admin restoration workflow.

  1. An admin views a list of only trashed posts: Post::onlyTrashed()->get().
  2. Each post in the list links to a review page, e.g., /admin/posts/1.
  3. Because the route uses ->withTrashed(), the model is successfully bound, and the admin can see the post’s content.
  4. The page then has a button to call the restore() method.

This approach gives you precise control. That ensures regular users see a 404 for deleted content while authorized users can still manage it.

Testing Soft Deletes in Laravel

Properly testing soft deletes ensures your application’s data safety net works as expected. Laravel’s testing helpers make it straightforward to verify all aspects of the soft delete lifecycle.

Testing the Soft Delete Action

To confirm a model can be soft deleted, assert that its deleted_at attribute is not null after calling the delete method.

public function test_it_can_soft_delete_a_model()
{
    $post = Post::factory()->create();
    $post->delete();
    $this->assertNotNull($post->deleted_at);
    $this->assertSoftDeleted($post); // Laravel's built-in assertion
}

Verifying Scoped Queries

A core function of soft deletes is to hide trashed records from normal queries.

public function test_it_excludes_soft_deleted_models_from_queries()

{

    $activePost = Post::factory()->create();

    $deletedPost = Post::factory()->create(['deleted_at' => now()]);

    $posts = Post::all();

    $this->assertCount(1, $posts);

    $this->assertTrue($posts->first()->is($activePost));

}

Testing Restoration and Permanent Deletion

Finally, verify that restoration and permanent deletion function correctly.

public function test_it_can_restore_a_soft_deleted_model()
{
    $post = Post::factory()->create(['deleted_at' => now()]);
    $post->restore();
    $this->assertNull($post->deleted_at);
    $this->assertNotSoftDeleted($post);
}
public function test_it_can_permanently_delete_a_model()
{
    $post = Post::factory()->create(['deleted_at' => now()]);
    $post->forceDelete();
    $this->assertModelMissing($post); // Asserts the record is gone from the database
}
Let’s build your dream project with Laravel!

Other Uses of Soft Deletes in Laravel

Laravel soft deletes offer a powerful tool for managing data beyond basic deletion functionality. Here are some additional valuable applications of soft deletes in Laravel applications:

1. Audit Trails

Soft deletes can be instrumental in maintaining a log of data changes. By keeping soft-deleted records along with their deleted_at timestamps, you can create a detailed audit trail. This allows you to track who deleted a record when it was deleted, and why it was deleted. It stores a reason alongside the deleted_at timestamp.

2. Temporary Inactivation

Soft deletes are ideal for scenarios where you need to temporarily deactivate user accounts, products, or other data entities. You can remove it from public view or functionality by soft deleting a record. Moreover, you can still preserve the data for potential future reactivation or reference.

3. Data Retention Policies

Soft deletes can help adhere to data retention policies or regulations. By keeping soft-deleted records for a specific period, you can ensure compliance with legal requirements before permanently deleting the data.

4. Shopping Carts and Checkouts

Soft deletes play a vital role in implementing shopping cart functionality. Users can add and remove items from their carts without permanently deleting the data from the database. Soft-deleted cart items can be easily identified and removed during the checkout process.

5. Undo Functionality

Soft deletes can be leveraged to create undo functionality within your application. If a user accidentally deletes data, you can provide an “undo” option that essentially restores the soft-deleted record. This enhances user experience by offering a safety net against accidental data loss.

These are just a few examples of how soft deletes can extend the functionality and flexibility of your Laravel applications. By using soft deletes, you can enhance data management and ensure compliance with various requirements.

Do’s & Don’ts of Soft Deletes in Laravel

Effectively managing soft deletes requires more than just implementation; it demands strategic thinking. Adhering to these best practices will prevent common pitfalls and ensure your data architecture remains robust.

Do’s

  • Do use unique constraints wisely. Remember that soft-deleted records still occupy unique indexes. Use unique constraints with a WHERE deleted_at IS NULL clause or consider composite keys.
  • Do create database indexes on the deleted_at column. This significantly improves query performance, especially for queries that frequently use withTrashed() or onlyTrashed().
  • Do implement a cleanup strategy. Soft-deleted records accumulate over time. Use Laravel’s Task Scheduling to run a periodic job that permanently deletes old records with forceDelete().
  • Do scope your models. Use local query scopes in your models for common queries like onlyActive(). That makes your code cleaner and more intentional.

Don’ts

  • Don’t use soft deletes for high-volume, transient data. Logs, session data, or cache records should typically be permanently deleted to avoid unnecessary database bloat.
  • Don’t forget to update your relationships. If a related model uses soft deletes, use the withTrashed() method within your relationship definitions when you always need the related record, even if it’s deleted.
  • Don’t treat it as an archive. Soft deletes are a safety net, not a primary archiving solution. For complex audit trails or historical data, use a dedicated status column or a separate archive table.
  • Don’t ignore the user experience. If a user “deletes” something, your UI should reflect that it’s gone, even if it’s soft-deleted in the backend. Provide a “Trash” view for users to manage their own deleted content where appropriate.

Follow these instructions to the tee and you’ll have the best results.

Let’s Conclude

Soft deletes in Laravel are a practical way to manage data safely. Instead of removing records completely, they’re marked as deleted using the deleted_at column. This allows you to keep the data for potential recovery or analysis, making your application more flexible.

Whether you’re handling user accounts, tracking data changes, or just need a safety net for accidental deletions, soft deletes can be a useful feature to implement. They’re easy to set up and can help make your data management more reliable.

If you need professional assistance to manage your Laravel database or want to improve your application’s functionality, hire Laravel developers today!

FAQs About Soft Deletes in Laravel

How to undo soft delete in Laravel?

Use the restore() method on the model. It will set the deleted_at column back to null, making the record active again.

What is the difference between hard delete and soft delete?

Hard delete removes the record permanently from the database, while soft delete only marks it as deleted, keeping the data for potential recovery.

What is the difference between soft delete and backup?

Soft delete keeps data in the same database with a “deleted” flag, while a backup creates a separate copy of the entire database or specific data to recover in case of loss.

How to view soft deleted data using Eloquent?

Use Eloquent built-in methods to query soft-deleted data. The withTrashed() method includes both active and trashed models in your results. To retrieve only soft-deleted records, use onlyTrashed().

author
Leading digital transformation projects with precision and creativity, Mayur turns complex ideas into results-driven web solutions. As Project Leader at WPWeb Infotech, he leverages his expertise in Laravel, PHP, Shopify, and Drupal to deliver innovation, scalability, and long-term success.

Protect Your Data with Laravel Soft Deletes

Recover deleted records easily and keep your data safe. Our Laravel experts can help you implement Soft Deletes effectively.