How to use softDeletes in Laravel with example
When working in production mode, delete method should not be permanently delete records from the database. There should be backup before delete them. Someone by mistake delete the data which was required. You might want to backup deleted records for future reference.
In this situation, Laravel provides soft delete feature which never delete data from database. It just hide them from showing. You can always get deleted data and restore or permanently delete them.
In this tutorial example, I will share you how you can build a softdelete system. We will go through step by step. So let's start from creating fresh Laravel application.
Step 1: Create a new Laravel application
First step always starts from creating new Laravel application. So open the Terminal or CMD and run the following command:
composer create-project laravel/laravel post
Change the directory to Laravel application root directory.
cd post
Step 2: Configure database
In the second step, we will set database credentials in the .env file. So import porject in your favourite text editor. Open file and change below credentials according to your MySQL database.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=post
DB_USERNAME=root
DB_PASSWORD=root
Step 3: Create migration
Now we will create database table to store data. So in the Terminal run the migration command.
php artisan make:migration create_posts_table
This will create a migration file at database/migrations directory. Open the migration file and add the table fields.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->softDeletes(); // this will create deleted_at field for softdelete
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
And run the migrate command to create table in database
php artisan migrate
Step 4: Create Model
In this step, we will create a model which will used to add SoftDeletes trait. Run the artisan command in Terminal.
php artisan make:model Post
This will create a Post model class at app/Models directory. Open model class and add the Illuminate\Database\Eloquent\SoftDeletes trait to the model. This will enable softdelete feature.
<?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;
}
Step 5: Create controller class
We will not implement whole CRUD operation. Instead we only implement Get records and delete feature. This will make tutorial simple and easy to understand how softdelete works. Run the following command in Terminal to create controller.
php artisan make:controller PostController
This will create a PostController
class at app/Http/Controllers
directory. Open controller and add the following methods in it. We will explain all methods one by one.
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if ($request->has('trashed')) {
$posts = Post::onlyTrashed()
->get();
} else {
$posts = Post::get();
}
return view('posts', compact('posts'));
}
/**
* soft delete post
*
* @return void
*/
public function destroy($id)
{
Post::find($id)->delete();
return redirect()->back();
}
/**
* restore specific post
*
* @return void
*/
public function restore($id)
{
Post::withTrashed()->find($id)->restore();
return redirect()->back();
}
/**
* restore all post
*
* @return response()
*/
public function restoreAll()
{
Post::onlyTrashed()->restore();
return redirect()->back();
}
}
Explanation of methods:
index() method views all post or soft deleted post.
destroy() method will soft delete specific post from the list
restore() method will restore specific post from list
restoreAll() method will restore all soft deleted post.
Step 6: Create routes
In this step, we need to create routes for controller. Common routes are located in routes/web.php file. So open file and add the following routes in it.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
Route::get('posts', [PostController::class, 'index'])->name('posts.index');
Route::delete('posts/{id}', [PostController::class, 'destroy'])->name('posts.destroy');
Route::get('posts/restore/{id}', [PostController::class, 'restore'])->name('posts.restore');
Route::get('posts/restore-all', [PostController::class, 'restoreAll'])->name('posts.restoreAll');
Step 7: Create blade file
In the last step of coding, we need to create view which will display and do all the stuff. So create a blade file resources/views/posts.blade.php.
<!DOCTYPE html>
<html>
<head>
<title>All Posts</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<div class="container">
<h1 class="m-3 text-center">All Posts</h1>
<table class="table table-bordered mb-3">
<thead>
<tr>
<th>No</th>
<th>Title</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach($posts as $post)
<tr>
<td>{{ $post->id }}</td>
<td>{{ $post->title }}</td>
<td>
@if(request()->has('trashed'))
<a href="{{ route('posts.restore', $post->id) }}" class="btn btn-success">Restore</a>
@else
<form method="POST" action="{{ route('posts.destroy', $post->id) }}">
@csrf
<input name="_method" type="hidden" value="DELETE">
<button type="submit" class="btn btn-danger delete" title='Delete'>Delete</button>
</form>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="float-end">
@if(request()->has('trashed'))
<a href="{{ route('posts.index') }}" class="btn btn-info">View All posts</a>
<a href="{{ route('posts.restoreAll') }}" class="btn btn-success">Restore All</a>
@else
<a href="{{ route('posts.index', ['trashed' => 'post']) }}" class="btn btn-primary">View Deleted posts</a>
@endif
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('.delete').click(function(e) {
if(!confirm('Are you sure you want to delete this post?')) {
e.preventDefault();
}
});
});
</script>
</body>
</html>
If you need to create fake records, insert below query to MySQL command prompt multiple times or use Factory.
INSERT INTO `posts` (`id`, `title`, `content`, `created_at`, `updated_at`, `deleted_at`) VALUES (NULL, 'Sticky footer with fixed navbar', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\r\ntempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\r\nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\r\nconsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\r\ncillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\r\nproident, sunt in culpa qui officia deserunt mollit anim id est laborum.', NULL, NULL, NULL);
Now our coding part is done. We need to start Laravel server using below command.
php artisan serve
In your browser, go to the url http://localhost:8000/posts and try to delete and restore post.
Conclusion
This way, you can backup and restore data which accidently deleted. I hope this tutorial will help you in your web development.
Copyright 2023 HackTheStuff