This post is also available in:
English
Soft Delete adalah fiture dari laravel untuk membuat penghapusan data sementara. kita bisa menghapus data pada tabel, tapi data tersebut tidak benar benar hilang atau di hapus, masih tersimpan datam tabel tapi tidak akan di tampilkan lagi.
Cara kerja softdelete pada laravel sebenarnya hampir mirip dengan recycle bin pada windows. Data yang kita hapus sebenarnya masih ada atau belum benar-benar dihapus permanen, jadi masih bisa ditampilkan kembali atau restored.
Cara kerja softdelete di database, jika data dihapus maka field deleted_at pada data tersebut akan terisi value timestamp. Kemudian jika data tersebut mau ditampilkan lagi atau restored maka value pada field deleted_at (sebelumnya terisi timestamp) akan diperbarui dengan NULL.
Install Laravel
composer create-project laravel/laravel softdelete
Buat Database
kemudian kalian buat database, saya rekomendasikan untuk menggunakan Migration saat membuat database.
Edit User Migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
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->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Tambahkan $table->softDeletes(); artinya kita akan menambahkan file delete_at yang mana jika data dalam kodisi soft delete, berarti di field delete_at akan berisi value timestamp dan jika tidak kondisi soft delete akan bernilai NULL. Jika sudah disimpan, silahkan jalankan php artisan migrate.
Edit User Model
Kemudian tambahkan use Illuminate\Database\Eloquent\SoftDeletes; dan use Softdeletes. Untuk model user yang terdapat di app\Models\User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable
{
use HasFactory, Notifiable, SoftDeletes;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Membuat Data Dummy dengan Factory
Jika kita cek di folder database/factories kita sudah memiliki file UserFactory.php, artinya kita bisa langsung saja menjalankan factory tanpa harus membuat file factory untuk tabel user lagi. Disini saya akan memberikan contoh bagaimana cara menjalankan factory dengan tinker di laravel. Apa itu tinker ? “interact with your application” itulah penjalasan dari laravel. Artinya kita bisa menjalankan pengujian seperti fetching data, menjalankan query hanya dari console

php artisan tinker
User::factory()->count(10)->create()
Buat File Global
Selanjutnya kita akan membuat file layouts yang kita beri nama global. File global ini nanti akan kita gunakan sebagai file master view, dimana nanti akan kita load di file index dan trash. Buat file di folder resources/views dengan nama global.blade.php.
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<title>Soft delete Laravel</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Bisabos.</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/">User</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Trash</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<div class="row">
@yield('content')
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>
</body>
</html>
Buat UserController.php
Kemudian kita memerlukan file UserController.php untuk menghandle ketika kita ingin menampilkan data, memindahkan data ke trash, restore data dan hapus data permanen. Jalankan command di atas pada terminal untuk membuat file UserController.php
php artisan make:controller UserController
public function index()
{
$user = User::all();
return view('index', ['user' => $user]);
}
Dengan kode di atas, kita akan menampilkan semua data user pada file index.blade.php yang akan kita buat di langkah selanjutnya.
Kemudian kita perlu membuat file view untuk menampilkan semua data user di database. Silahkan buat file view baru dengan nama index.blade.php, kemudian copy semua kode di atas lalu paste di file index.blade.php yang baru saja dibuat.
@extends('global')
@section('content')
<div class="mx-auto border-bottom mb-3">
<h1 class="text-center">Soft Delete Laravel</h1>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Option</th>
</tr>
</thead>
<tbody>
@php
$no = 0;
@endphp
@foreach ($user as $user)
<tr>
<th scope="row">{{ ++$no }}</th>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
Option
</td>
</tr>
@endforeach
</tbody>
</table>
@endsection
Update route web.php
Selanjutnya buka file routes/web.php, kemudian ganti saja semua kode di file tersebut dengan kode di atas. Pada halaman root, kita akan memanggil function index yang ada di file UserController, yang mana function index ini digunakan untuk menampilkan semua data user.
<?php
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', [UserController::class, 'index']);
Sekarang kalau kita jalankan projek, di halaman root projek kita akan menampilkan tampilan seperti gambar di atas. Sampai sini kita sudah bisa memanggil atau menampilkan data user dari database ke view. Dilangkah selanjutnya kita akan membuat function destroy dan tombol delete, dimana saat kita jalankan atau klik tombol delete maka data akan dipindahkan ke trash (bukan hapus permanen).
Tambahkan function destroy
public function destroy($id)
{
$user= User::findOrFail($id);
$user->delete();
return redirect('/');
}
Tambah route
Route::delete('{id}/destroy', [UserController::class, 'destroy'])->name('destroy');
Menambahkan tombol delete (Soft Delete)
<form method="POST" class="d-inline" onsubmit="return confirm('Move data to trash?')" action="{{route('destroy', [$user->id])}}">
@csrf
<input type="hidden" value="DELETE" name="_method">
<input type="submit" value="Delete" class="btn btn-danger btn-sm">
</form>
Nah, selanjutnya kita perlu menambahkan tombol delete di file view index. Dimana saat tombol delete ini kita klik, akan menampilkan confirm dialog “Move data to trash ?” dan jika kita klik OK maka data tidak akan ditampilkan lagi atau akan dipindahkan ke trash. Buka file index.blade.php, pada <td>Option</td> ganti dengan kode di atas.
Jika kita cek di database pada record dari data yang kita hapus, data tidak sepenuhnya langsung hilang di database melainkan hanya disembunyikan dengan menambahkan value timestamp pada field deleted_at.
Membuat Function Trash
Kita lanjutkan dengan membuat function baru yang berfungsi untuk menampilkan data yang sudah dalam kondisi soft delete. Buka file UserController.php, kemudian copy code di atas dan tambahkan di UserController.php. Dengan kode onlyTrashed di atas berarti akan menampilkan data yang mempunyai value timestamp di field deleted_at.
public function trash()
{
$user = User::onlyTrashed()->paginate(10);
return view('trash', ['user' => $user]);
}
Menambahkan route
Daftarkan route di web.php yang mengarahkan ke function trash di UserController. Buka file web.php, kemudian copy kode di atas dan tambahkan di web.php
Route::get('trash', [UserController::class, 'trash'])->name('trash');
Membuat View Trash
Setelah membuat function trash dan mendaftarkannya di route web.php, kita juga perlu membuat file view baru yang akan kita fungsikan untuk menampilkan data-data dengan kondisi softdelete. Buat file view baru dengan nama trash.blade.php, copy semua code di atas dan paste di file view trash yang baru saja dibuat.
@extends('global')
@section('content')
<div class="mx-auto border-bottom mb-3">
<h1 class="text-center">Soft Delete Laravel</h1>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Option</th>
</tr>
</thead>
<tbody>
@php
$no = 0;
@endphp
@foreach ($user as $user)
<tr>
<th scope="row">{{ ++$no }}</th>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
option
</td>
</tr>
@endforeach
</tbody>
</table>
@endsection
Sekarang jika kita arahkan ke URL /trash maka akan menampilkan data-data yang sebelumnya sudah dihapus namun masih tersimpan di database (softdelete). Pada row option nanti akan kita tambahkan tombol restore yang mana jika tombol tersebut diklik akan mengembalikan data dari trash ke index dan tombol delete (permanent).
Edit Navbar
Untuk memudahkan kita dalam berpindah-pindah halaman index – trash, ada baiknya kita edit dulu pada bagian navbar.
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/">User</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Trash</a>
</li>
</ul>
</div>
Silahkan buka file view global.blade.php, kemudian cari kode di atas. Setelah itu ganti kode di atas dengan kode di bawah ini.
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/">User</a>
</li>
<li class="nav-item">
<a class="nav-link" href="trash">Trash</a>
</li>
</ul>
</div>
Membuat Function Restore
public function restore($id)
{
$user = User::withTrashed()->findOrFail($id);
if($user->trashed()){
$user->restore();
return redirect()->route('trash')->with('status', 'Data successfully restored');
} else {
return redirect()->route('trash')->with('status', 'Data is not in trash');
}
}
Pada langkah ini kita akan membuat function yang berfungsi untuk restore atau mengembalikan data dari trash ke index. Caranya bisa langsung saja copy kode di atas lalu tambahkan di UserController.
Penjelasan singkat mengenai kode di atas, jadi kita akan mencari atau seleksi data dengan parameter $id dan dengan kondisi soft delete (withTrashed). Apabila data ditemukan, maka data tersebut akan dikembalikan atau restore.
Menambahkan Route Restore
Sebelumnya kita sudah membuat atau menambahkan function restore untuk mengembalikan atau memindahkan data dengan kondisi soft delete ( trash ) ke halaman index. Hal yang perlu kita lakukan selanjutnya adalah dengan mendaftarkan route restore di file routes/web.php. Caranya bisa langsung saja copy kode di atas lalu tambahkan di file routes/web.php.
Route::post('{id}/restore', [UserController::class, 'restore'])->name('restore');
Menambahkan Tombol Restore
<form method="POST" action="{{route('restore', [$user->id])}}" class="d-inline">
@csrf
<input type="submit" value="Restore" class="btn btn-success"/>
</form>
Nah sekarang kita akan menambahkan tombol restore di file view trash. Seperti nama dan tujuan route ( restore ), tombol ini berfungsi untuk mengembalikan data dari kondisi soft delete di halaman trash dipindahkan lagi ke halaman index. Artinya value timestamp di field deleted_at pada data tersebut juga akan dihapus dan dikembalikan lagi ke NULL. Langsung saja kita tambahkan kodenya dengan membuka file trash.blade.php, pada baris <td>Action<td> ganti action dengan kode di atas.
@if(session('status'))
<div class="alert alert-success text-center">
{{session('status')}}
</div>
@endif
Kemudian untuk menampilkan status saat data dengan kondisi soft delete berhasil di restore atau tidak, kita perlu menambahkan kode di atas pada file trash.blade.php juga. Karena jika kita perhatikan pada file UserController, ada beberapa function yang redirect diikuti dengan menampilkan pesan status. Langsung saja copy kode di atas, lalu tambahkan di file trash.blade.php atau lebih tepatnya di bawah <h1 class=”text-center”>Soft Delete Laravel</h1>.
Sekarang, kalau kita coba buka halaman trash, kemudian kita klik tombol restore yang ada disamping data yang ada maka data akan dipindahkan lagi ke index dengan diikuti pesan status “Data successfully restored” di bawah title “Soft Delete Laravel”.
Membuat Function Delete Permanent
public function deletePermanent($id)
{
$user = User::withTrashed()->findOrFail($id);
if(!$user->trashed())
{
return redirect()->route('trash')->with('status', 'Data is noting trash!');
} else {
$user->forceDelete();
return redirect()->route('trash')->with('status', 'Data permanently deleted!');
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UserController extends Controller
{
public function index()
{
$user = User::all();
return view('index', ['user' => $user]);
}
public function destroy($id)
{
$user = User::findOrFail($id);
$user->delete();
return redirect('/');
}
public function trash()
{
$user = User::onlyTrashed()->paginate(10);
return view('trash', ['user' => $user]);
}
public function restore($id)
{
$user = User::withTrashed()->findOrFail($id);
if($user->trashed()){
$user->restore();
return redirect()->route('trash')->with('status', 'Data successfully restored');
} else {
return redirect()->route('trash')->with('status', 'Data is not in trash');
}
}
public function deletePermanent($id)
{
$user = User::withTrashed()->findOrFail($id);
if(!$user->trashed())
{
return redirect()->route('trash')->with('status', 'Data is noting trash!');
} else {
$user->forceDelete();
return redirect()->route('trash')->with('status', 'Data permanently deleted!');
}
}
}
Route::delete('{id}/delete-permanent', [UserController::class,'deletePermanent'])->name('deletePermanent');
<?php
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', [UserController::class, 'index']);
Route::delete('{id}/destroy', [UserController::class, 'destroy'])->name('destroy');
Route::get('trash', [UserController::class, 'trash'])->name('trash');
Route::post('{id}/restore', [UserController::class, 'restore'])->name('restore');
Route::delete('{id}/delete-permanent', [UserController::class,'deletePermanent'])->name('deletePermanent');
Dengan dita
Menambahkan Tombol Delete (Permanent)
<form method="POST" action="{{route('deletePermanent', [$user->id])}}" class="d-inline" onsubmit="return confirm('Delete this data permanently ?')">
@csrf
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="Delete" class="btn btn-danger">
</form>
@extends('global')
@section('content')
<div class="mx-auto border-bottom mb-3">
<h1 class="text-center">Soft Delete Laravel</h1>
@if(session('status'))
<div class="alert alert-success text-center">
{{session('status')}}
</div>
@endif
</div>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Option</th>
</tr>
</thead>
<tbody>
@php
$no = 0;
@endphp
@foreach ($user as $user)
<tr>
<th scope="row">{{ ++$no }}</th>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
<form method="POST" action="{{route('restore', [$user->id])}}" class="d-inline">
@csrf
<input type="submit" value="Restore" class="btn btn-success"/>
</form>
<form method="POST" action="{{route('deletePermanent', [$user->id])}}" class="d-inline" onsubmit="return confirm('Delete this data permanently ?')">
@csrf
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="Delete" class="btn btn-danger">
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
@endsection
Comments 1