DEV Community

Kingsconsult
Kingsconsult

Posted on

How to create Recycle Bin with Soft Delete in Laravel 8 and 7

Hello guys, I want to treat some Laravel concepts about deleting, sometimes we may want to design our application so that even though the user deletes a data, it is not permanently deleted, it will still remain in the database but will not show up in the view. Laravel has provided this functionality out of the box for us called softDelete, so I am going to illustrate how to delete data and view the deleted data and also how to restore the deleted data, and finally, how to permanently delete the data, I called this concept Recycle Bin.
We are going to be using the code from my previous article Laravel 8 CRUD App, A simple guide, the repo

If you prefer videos, you can watch the video from Youtube

Click on my profile to follow me to get more updates.

Step 1: Setup the app

  1. git clone https://github.com/Kingsconsult/laravel_8_crud.git
  2. cd laravel_8_crud/
  3. composer install
  4. npm install
  5. cp .env.example .env
  6. php artisan key:generate
  7. Add your database config in the .env file (you can check my articles on how to achieve that)
  8. php artisan migrate
  9. php artisan serve (if the server opens up, http://127.0.0.1:8000, then we are good to go) localhost
  10. Navigate to http://127.0.0.1:8000/projects

Step 2: Add delete_at column to projects table

In Laravel Soft Delete, data are not actually deleted from the database but a deleted_at attribute is added to the data, so when we are querying data from the database, Eloquent looks for data with null deleted_at value and give out, but when a data has non-null deleted_at value, it treats it as a deleted data.
So we need to add it and run our migration again.
create migration file

Step 3: Add the delete_at column to the migration file

Running the command in step 2 will create a migration file in database/migrations/, edit the file and add $table->softDeletes(); to the up() function and also $table->dropSoftDeletes(); to the down() function, our migration file looks like this
migration file

Step 4: Run migration again

We need to run the migration again so that the new column will be added to the existing table

php artisan migrate

migration
Going to our database, you will see the new column created with values Null
database

Step 5: Enable the softdelete trait on the model

Go to app/Models/Project.php and add the soft delete trait, this trait will tell the model to only add a date to the model that is deleted, but not deleting it permanently.

use SoftDeletes;

Also, add the path of the trait at the top

use Illuminate\Database\Eloquent\SoftDeletes;

Step 6: Create the routes to get all deleted projects

Go to routes/web.php and add the route to get all deleted projects

Route::get('projects/deletedprojects', [ProjectController::class, 'getDeleteProjects'])->name('getDeleteProjects');

Step 7: Create the Controller Method

In our route above, we specified a getDeletedProjects methods in the ProjectController class, so we create that method. Go to app/Http/Controllers/ProjectController.php and add this method

    public function getDeleteProjects() {
        $projects = Project::onlyTrashed()->paginate(10);

        return view('projects.deletedprojects', compact('projects'))
            ->with('i', (request()->input('page', 1) - 1) * 10);
    }
Enter fullscreen mode Exit fullscreen mode

From the method above, we used an eloquent function onlyTrashed(), this function only fetches the model with non-null deleted_at values, so it will fetch just the projects that are deleted.

Step 8: Create the blade file to view all deleted project

From our getDeletedProjects() method above, we return to deletedprojects view, so we need to create that, go to resources/views/projects/ and create the file deletedprojects.blade.php and copy the index page and edit to this

@extends('layouts.app')

@section('content')
    <div class="row">
        <div class="col-lg-12 margin-tb">
            <div class="pull-left">
                <h2>Laravel 8 CRUD </h2>
            </div>
        </div>
    </div>

    <div class="pull-left ">
        <a class="btn btn-success" href="{{ route('projects.index') }}" title="Back to Index"> <i class="fas fa-home"></i> </a>
    </div>
    <div class="">
        <div class="mx-auto pull-right">
            <div class="">
                <form action="{{ route('projects.index') }}" method="GET" role="search">

                    <div class="input-group">
                        <span class="input-group-btn mr-5 mt-1">
                            <button class="btn btn-info" type="submit" title="Search projects">
                                <span class="fas fa-search"></span>
                            </button>
                        </span>
                        <input type="text" class="form-control mr-2" name="term" placeholder="Search projects" id="term">
                        <a href="{{ route('projects.index') }}" class=" mt-1">
                            <span class="input-group-btn">
                                <button class="btn btn-danger" type="button" title="Refresh page">
                                    <span class="fas fa-sync-alt"></span>
                                </button>
                            </span>
                        </a>
                    </div>
                </form>
            </div>
        </div>
    </div>

    @if ($message = Session::get('success'))
        <div class="alert alert-success">
            <p>{{ $message }}</p>
        </div>
    @endif

    <table class="table table-bordered table-responsive-lg">
        <tr>
            <th>No</th>
            <th>Name</th>
            <th>Introduction</th>
            <th>Location</th>
            <th>Cost</th>
            <th>Date Deleted</th>
            <th>Action</th>
        </tr>
        @foreach ($projects as $project)
            <tr>
                <td>{{ ++$i }}</td>
                <td>{{ $project->name }}</td>
                <td>{{ $project->introduction }}</td>
                <td>{{ $project->location }}</td>
                <td>{{ $project->cost }}</td>
                <td>{{ date_format($project->deleted_at, 'jS M Y') }}</td>
                <td>
                    <a href="{{ route('restoreDeletedProjects', $project->id) }}" title="restore project">
                        <i class="fas fa-window-restore text-success  fa-lg"></i>
                    </a>
                    <a href="{{ route('deletePermanently', $project->id) }}" title="Permanently delete">
                        <i class="fas fa-trash text-danger  fa-lg"></i>
                    </a>
                </td>
            </tr>
        @endforeach
    </table>

    {!! $projects->links() !!}


@endsection
Enter fullscreen mode Exit fullscreen mode

In the action column of a project from the code above, we added an icon to restore a deleted file, this will remove the value in the deleted_at in the table and we also added another icon to delete a project permanently, this will permanently delete the project from the database.
Next, we need to create a function to restore the deleted project.

Step 9: Create Route to Restore Deleted Project

Route::get('projects/deletedprojects/{id}', [ProjectController::class, 'restoreDeletedProjects'])->name('restoreDeletedProjects');

In our route, we also specify a controller method restoreDeletedProjects, so we head to ProjectController and create the method

Step 10: Create Controller Method to Restore Deleted Project

Go to app/Http/Controllers/ProjectController.php and add this method

    public function restoreDeletedProjects($id) 
    {

        $project = Project::where('id', $id)->withTrashed()->first();

        $project->restore();

        return redirect()->route('projects.index')
            ->with('success', 'You successfully restored the project');
    }
Enter fullscreen mode Exit fullscreen mode

Step 11: Create Route to permanently delete Project

We need to also create a functionality, to permanently delete a project that we don't want to leave in the database, so let's create the route

Route::get('projects/retoreprojects/{id}', [ProjectController::class, 'deletePermanently'])->name('deletePermanently');

Step 12: Create the Controller Method

    public function deletePermanently($id)
    {
        $project = Project::where('id', $id)->withTrashed()->first();

        $project->forceDelete();

        return redirect()->route('projects.index')
            ->with('success', 'You successfully deleted the project fromt the Recycle Bin');

    }
Enter fullscreen mode Exit fullscreen mode

That is all, let's test our work
We created some projects,
index with all projects
We also added a recycle icon that will take us to the page that we display all deleted projects, then we deleted two of the projects and going to the recycle page
recycle page

restored project
These are the projects we deleted from the index page, here we have two icons, one to restore deleted projects and the other to permanently delete the project from the database
We restored a project, and it returns to the index, then finally, we deleted the other permanently
permanently deleting a project

You can get the complete code from the Github repo.
Follow me for more of my articles, you can leave comments, suggestions, and reactions.
I am open to any vacancy as a PHP backend engineer, my strength is in the Laravel framework

click the link to view my profile and follow me

Top comments (2)

Collapse
 
waltun profile image
Pooriya Mostaan

Very helpful,
Thanks

Collapse
 
tatendawil profile image
tatesoft

thanks alot this is helpful