How to Restore Deleted Data using Soft-Delete in Laravel
Laravel Soft Delete is a very useful option from Laravel Eloquent if you want to use it as a recycle bin before permanently deleting data. In case some data gets deleted accidentally, Laravel has the option to restore the deleted data. So, you can use this feature as trash data. You can also permanently delete the data using the Laravel force delete option.
To use soft delete feature in your Laravel application:
While creating the migration use $table->softDeletes(); for the table you want to use Soft-Delete. This will add "deleted_at" column in the table.
In the model add use Illuminate\Database\Eloquent\SoftDeletes; and add use SoftDeletes; trait.
In the controller use delete() method on the selected row to move data to trash. It actually updates the "deleted_at" column with the timestamp.
To Restore - Use restore() method in the controller to restore deleted data.
To Permanently Delete - use forceDelete() method in the controller for the selected rows from Trashed data.
Please read the entire topic to implement all these. We will develop a Laravel application to show how Soft Delete works. We will have a list of training courses with the option to delete each course. After deleting you can view the trashed data with the option to restore it or delete it permanently.
We will create a Laravel project using the below command. You need to have the composer and PHP installed in your computer. We are using the project name as lara_soft_delete.
This command will create lara_soft_delete folder and install all necessary files in it. So, our project root folder is "lara_soft_delete".
Step 2 - Create Laravel migration
We will create a table named 'training_courses' using Laravel migration. This table will store the details of all courses. Go to your project root folder and run the below command from VS code terminal. It will create the model, controller and migration.
php artisan make:model TrainingCourse -mc
The option "mc" will create the model (TrainingCourse.php), controller (TrainingCourseController.php) and the migration file (create_training_courses_table.php with a datetime prefix).
Create a database named "lara_demo" for this project using phpMyAdmin and update the .env file for database details as below:
We will create the migration file for a new table named 'training_courses' and will use $table->softDeletes(); in it.
public function up()
{
Schema::create('training_courses', function (Blueprint $table) {
$table->id();
$table->string('course_title');
$table->string('course_descr');
$table->string('level');
$table->string('duration');
$table->softDeletes(); // for soft delete
$table->timestamps();
});
}
So, our table will have course_title, course_descr, level (basic, Intermediate etc.) and duration columns along with the column "deleted_at" for soft delete.
We will now run the migration to create the default Laravel tables and our custom table. Run the below artisan command from the project root to create the tables.
php artisan migrate
This will create all the default Laravel tables as well as our custom 'training_courses' table. After migration see the structure of the table.
Now let us update the model for soft delete. Use SoftDelete Trait here. Below is the model:
app/Models/TrainingCourse.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class TrainingCourse extends Model
{
use HasFactory;
use SoftDeletes;
}
Create Laravel Database Seeder
We will create some dummy data for the courses. Run the below command to create a seeder file:
php artisan make:seeder TrainingCourseSeeder
Update seeder file as below to insert 3 rows in training_courses table:
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class TrainingCourseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::table('training_courses')->insert([
'course_title' => 'Core PHP',
'course_descr' => 'CodeIgniter',
'level' => 'Intermediate',
'duration' => '2 weeks'
]);
DB::table('training_courses')->insert([
'course_title' => 'JavaScript',
'course_descr' => 'Basic JavaScript',
'level' => 'Basic',
'duration' => '1 week'
]);
DB::table('training_courses')->insert([
'course_title' => 'Core PHP',
'course_descr' => 'Training for Core PHP',
'level' => 'Basic',
'duration' => '1 week'
]);
}
}
Update run() method of the database seeder file (database/seeders/DatabaseSeeder.php) as below to call our seeder file:
public function run()
{
$this->call(TrainingCourseSeeder::class);
}
Now run the below command to create the rows:
php artisan db:seed
After running this command, you will see the three rows inserted in the database table.
Step 3 - Controller code
Controller will have few methods for each of the actions performed on the course.
index() method to display all the courses.
moveToTrash() to move data to trash, i.e., soft delete.
showTrash() method to display all trashed data. These data can be restored or deleted permanently.
restore() method to restore the deleted row.
forceDelete() method to delete data from trash permanently.
Let us see the code for the controller
app/Http/Controllers/TrainingCourseController.php
namespace App\Http\Controllers;
use App\Models\TrainingCourse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
class TrainingCourseController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$courses = TrainingCourse::all();
return view('view_courses', compact('courses'));
}
public function moveToTrash(Request $request)
{
$id = $request->delete;
TrainingCourse::findOrFail($id)->delete();
Session::flash('message', 'Course Moved to Trash');
return redirect()->route('course.index');
}
public function showTrash()
{
$trash_course = TrainingCourse::onlyTrashed()->get();
return view('trashed_courses', compact('trash_course'));
}
public function restore(Request $request)
{
$id = $request->restore;
$data = TrainingCourse::withTrashed()->find($id);
if (!is_null($data)) {
$data->restore();
Session::flash('message', 'Course restored');
}
return redirect()->route('show.trashed');
}
public function forceDelete(request $request)
{
$id = $request->delete;
$data = TrainingCourse::withTrashed()->find($id);
if (!is_null($data)){
$data->forceDelete();
Session::flash('message', 'Course deleted');
}
return redirect()->route('show.trashed');
}
}
Step 4 - Laravel blade views
We will create two views, one for listing all courses and the other for viewing all deleted (trashed) data. Along with them, we will have layouts and a couple of modals for user confirmations before deleting.
We have the below files in the resources/views folder
header, footer and master are for the layouts. view_courses.blade.php is for the listing of all courses, trashed_courses.blade.php is the list of all trashed(soft deleted) courses.
In the above code, we have a simple list of all courses with a delete button (an icon for trash) against each course. A modal for confirmation will open when it is clicked. Also, a JavaScript function is called just to write the id of course in a form in the modal for confirmation. We will see it in the modal.
This will list all deleted or trashed data. Against each row, there are two buttons; one for restoring and the other for permanent deletion. There will be a confirmation modal for each of the actions.