In this tutorial, You are going to learn about soft delete in laravel. By using soft delete, instead of removing data from the database, laravel uses a deleted_at column which is a timestamp and nullable by default.
You need a deleted_at column, which can be easily done by adding $table->softDeletes(); into migration schema. After adding column you need to use SoftDeletes trait into the model.
Laravel shipped with default users table migration. First of all, modify the users table schema as below. I removed unnecessary fields and added softDeletes column into it.
/* database > migrations > *_create_users_table.php */
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->softDeletes();
$table->timestamps();
});
}
Next, replace the User model with the following code. I kept the User model as simple as possible.
/* app > User.php */
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
protected $fillable = [
'name', 'email'
];
}
Finally, migrate database with following command.
php artisan migrate
That’s it! This is a fully functional setup for soft delete for the User model. An example will give you a clear idea. Let’s use users table as an example.
Post Contents
# Seeding Users Table (Optional)
Create UsersTableSeeder with the following command, and update following code into it.
php artisan make:seeder UsersTableSeeder
/* database > seeds > UsersTableSeeder.php */
<?php
use App\User;
use Illuminate\Database\Seeder;
use Faker\Factory as Faker;
class UsersTableSeeder extends Seeder
{
public function run()
{
$faker = Faker::create();
foreach(range(1,10) as $index)
{
User::create([
'name' => $faker->userName,
'email' => $faker->safeEmail
]);
}
}
}
In above function, I’m using faker for generating dummy data. Logic is simple, using range function you can loop through given number.
Next, we need to tell laravel which table needs seeding. For that, open DatabaseSeeder.php and replace the below code.
/* database > seeds > DatabaseSeeder.php */
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call(UsersTableSeeder::class);
}
}
Migrate and seed users table with following command to generate users.
php artisan migrate:refresh --seed
# Displaying Users
Let’s create UsersController with following command, and replace below code.
php artisan make:controller UsersController
/* app > Http > Controllers > UsersController.php */
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class UsersController extends Controller
{
public function index()
{
$users = User::all();
$trashedUsers = User::onlyTrashed()->get();
return view('users', compact('users', 'trashedUsers'));
}
public function delete(Request $request)
{
User::destroy($request->user_id);
return redirect()->back()->with("msg", "User removed successfully.");
}
public function restore(Request $request)
{
User::where('id', $request->user_id)->restore();
return redirect()->back()->with("msg", "User restored successfully.");
}
}
In index function, I fetched all users and onlyTrashed users. When retriving all users, trashed users will automatically removed from response.
Next, create routes to handle this functions.
/* routes > web.php */
<?php
Route::get('/', 'UsersController@index')->name('users.index');
Route::delete('user/delete/{user_id}', 'UsersController@delete')->name('user.delete');
Route::get('user/restore/{user_id}', 'UsersController@restore')->name('user.restore');
Finally, create users.blade.php and modify it as below.
/* resources > views > users.blade.php */
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Laravel Soft Delete</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<div class="container my-5 align-center">
@if(session()->has('msg'))
<div class="alert alert-info alert-dismissible">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ session()->get('msg') }}
</div>
@endif
<div class="row">
{{-- Users List --}}
<div class="col-md-6">
<table class="table table-striped">
<thead>
<tr class="bg-primary text-white">
<th colspan="3" align="center">Current Users</th>
</tr>
<tr>
<th>Name</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
<button class="btn btn-danger btn-sm" onclick="event.preventDefault();document.getElementById('user_delete_{{ $user->id }}').submit();">
<span class="fa fa-trash"></span></button>
</td>
<form action="{{ route('user.delete', $user->id) }}" method="POST" id="user_delete_{{ $user->id }}">
{{ csrf_field() }}
{{ method_field('DELETE') }}
</form>
</tr>
@endforeach
</tbody>
</table>
</div>
{{-- Trashed Users List --}}
<div class="col-md-6">
<table class="table table-striped">
<thead>
<tr class="bg-primary text-white">
<th colspan="3" align="center">Trashed Users</th>
</tr>
<tr>
<th>Name</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach($trashedUsers as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td><a href="{{ route('user.restore', $user->id) }}" class="btn btn-info btn-sm"><span class="fa fa-refresh"></span> Restore</a></td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
Start php server with following command and open localhost:8000 in browser.
php artisan serve
As you can see, you will have two tables which have current and trashed users. After deleting a user from current users it will be displayed in the trashed users. Similarly, after restoring a user from trashed users it will be displayed in current users.
# Force Delete Users
If you want to force delete users just update delete method in UsersController.
/* app > Http > Controllers > UsersController.php */
....
public function delete(Request $request)
{
User::where('id', $request->user_id)->forceDelete();
return redirect()->back()->with("msg", "User removed successfully.");
}
....
Remember, force deleted users are not restorable. Try to delete a user after updating the delete function. You will see users not displaying in the trashed users list.