Laravel How to Implement Soft Deletes

Hello Artisan, today I'll show you how to implement Soft Deletes in Laravel. Soft Deletes is a feature in Laravel that allows you to delete database records without actually removing them from the database. When a record is soft deleted, it is marked as deleted in the database, but still exists in the database and can be retrieved. This feature is useful for applications where you don't want to permanently delete records but want to keep a record of deleted items.

Note: Tested on Laravel 10.8

Table of Contents

  1. Usage of Soft Deletes
  2. Methods for Soft Deleted Model

Usage of Soft Deletes

First we'll see how to use soft delete. First add a deleted_at column in your table by specifying the below in your migration table. So, we'll use the default users migration which is come with laravel by default. So, add the below code in your users migration 

$table->softDeletes();

So, your users migration file will look like below

database/migrations/2014_10_12_000000_create_users_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->softDeletes();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

Then we've to use SoftDeletes trait in our model. So, our model will look like below

app/Models/User.php
<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

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

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

And it's done. Now when we delete any user then it'll sets the deleted_at column by default to current timestamp.

Deleted_at column set to current timestamp

Methods for Soft Deleted Model

We already delete a row in #step1, but how we'll retrive theme. Because usually how we use to get result, this will exclude the soft deleted model. So, for retrieving records that have been deleted as well, we've to use the withTrashed() method:

$users = User::withTrashed()->get();

This will retrieve all the record of DB including soft deleted row as well. And if we only want to get Soft Deleted row, we can use onlyTrashed() method:

$users = User::onlyTrashed()->get();

And to restore a soft deleted model we can use restore() method.

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

And if we want to permanently deletes a user like we normally did, we've to use forceDelete() method. Because we already saw in #step1, that if we use a row it'll updates the only deleted_at column. So, we've to use the below code to permanently delete a user.

User::find(1)->forceDelete(); 

And if you want to permanently delete a soft deleted user then you can use the below code

User::onlyTrashed()->find(1)->forceDelete()

That's it for today. Hope this tutorial will be helpful in your upcoming projects. Thanks for reading. 🙂