Mengenal apa itu soft delete di laravel

Mengenal apa itu soft delete di laravel


Selamat pagi, siang, sore atau malam sobs-sobs sekalian, semoga sobs-sobs masih diberikan kesehatan sehingga bisa membaca artikel ini dengan ditemani kopi hitam panas dan seutas gorengan.

Oke pada pembahasan kali ini kita akan membahas tentang si framework tamvan yaitu Laravel dengan fokus pada fiturnya yaitu soft delete

Bagi yang sudah familiar dengan materi ini boleh di skip terlebih dahulu, dan bagi yang belum mari kita mulai dengan apa yang dimaksud soft delete di laravel, 

Soft delete adalah sebuah mekanisme menghapus data secara temporary atau sementara, biasanya jika sobs-sobs sekalian menghapus data dilaravel maka data tersebut sepenuhnya hilang benar-benar tidak ada, maka dengan soft delete ini sebenarnya data tidak dihapus hanya saja akan dihide atau disembunyikan jika kita melakukan query konsep seperti ini sama seperti recycle bin. hehehe sorry ya kalo analoginya sedikit ngaco.

Sebenarnya prinsip kerja cukup sederhana jika sebelumnya dilaravel kita membuat file migrasi secara default maka akan ada schema $table->timestamps dimana itu digunakan untuk membuat kolom didatabase yaitu created_at  dan updated_at, nah jika kita ingin suatu resource kita menggunakan soft delete maka kolom deleted_at akan kita buat juga.

Oke dari pada bingung disini gua akan buat contohnya dengan membuat Model Employee beserta file migrasinya :


php artisan make:model Employee --migration --seed

Jika sudah silahkan sobs-sobs buka migration filenya terlebih dahulu, 
untuk membuat suatu table menggunakan mekanisme soft delete terdapat dua cara untuk kita membuat kolom deleted_at dengan tipenya yaitu timestamp.


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('employees', function (Blueprint $table) {
            $table->id();
            $table->string('name', 100);
            $table->string('email', 100)->unique();
            $table->timestamps();

            // cara pertama
            // $table->timestamp('deleted_at')->nullable();

            // cara kedua (rekomendasi)
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('employees');
    }
};



Perhatikan sobs-sobs

cara 1: Kita membuat kolom dengan tipe data timestamp dan dengan nama deleted_at yang mana kolom tersebut nullable artinya boleh kosong, yang perlu diperhatikan adalah penamaan pada kolom harus mengikuti aturan yang sudah ditetapkan oleh laravel yaitu deleted_at dan jika kita typo maka soft delete tidak akan berkerja oleh karena itu cara pertama kirang direkomendasikan.

cara 2: Kita hanya menggunakan method dari blueprint $table yaitu softDeletes(), dimana method ini otomatis akan membuat kolom dengan nama deleted_at dengan tipe timestamp cara kedua ini sangat direkomendasikan. jangan lupa untuk menjalankan migrasi filenya


Oke, jika kita sudah melakukan hal diatas maka belum selesai selanjutnya kita ke file model yaitu
app/Models/Employee.php

walaupun kita sudah membuat kolom deleted_at kita belum bisa menggunakan softdelete ada satu tahapan lagi sobs-sobs yaitu kita harus mengimplementasikan trait SoftDelete didalam model kita. seperti contoh dibawah ini :


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Employee extends Model
{
    use HasFactory;

    // implementasi trait soft delete
    use SoftDeletes;


    protected $guarded = ['id'];
}



trait soft delete ini berada di Illuminate\Database\Eloquent\SoftDeletes lalu kita implementasikannya dengan mengunakan keyword use.

untuk melakukan pengujian pertama-tama gua akan mengisi file seeder yang sebelumnya sudah dibuat
database/seeder/EmployeeSeeder.php


<?php

namespace Database\Seeders;

use App\Models\Employee;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class EmployeeSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Employee::create([
            'name' => 'sruputkode',
            'email' => 'sruputkode@outlook.co.id',
        ]);

        Employee::create([
            'name' => 'kirana',
            'email' => 'kirana@outlook.co.id',
        ]);
    }
}


diatas gua buat dua contoh data employee sobs-sobs, selanjutnya untuk pengetesan gua akan buat sebuah unit test, lah bang kok testnya engga lewat controller ?
Hehe magerr intinya sama saja sobs.

oke langsung saja kita buat unit testnya

php artisan make:test SoftDeleteTest


Selanjutnya kita buka file unit testnya yang berada di test/Feature/SoftDeleteTest.php

kita hapus method bawaannya menjadi seperti ini :

<?php

namespace Tests\Feature;

use App\Models\Employee;
use Database\Seeders\EmployeeSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;

class SoftDeleteTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        DB::delete('DELETE FROM employees');
    }

    // unit test softDelete
    public function testDelete()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // delete
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->delete();

        // ambil semua data employee
        $employees = Employee::all();
        self::assertCount(1, $employees);
    }
}


Penjelasan :

Method setUp : adalah method yang selalu dieksekusi jika kita menjalankan unit test, didalam method tersebut artinya setiap kita menjalankan unit test maka table employees akan dikosongkan terlebih dahulu ya sobs.

skema unit test
1. Pertama kita akan melakukan seeder dimana akan terdapat dua buah data employe
2. Selanjutnya Menghapus data employee dengan nama sruputkode
3. Query select semua data employee dan kita dapat hasil bahwa data tinggal 1.

tampilan unit test akan seperti dibawah ini


Untuk di Visual Studio Code sobs-sobs bisa mencari extension PHP Unit Test, extension tersbut berguna memudahkan kita melakukan unit test, seperti tampilan diatas maka akan ada tombol Run Test Kita tinggal klik saja untuk menjalankan unit test.

Sekarang silahkan sobs-sobs buka PHPMyAdmin sobs-sobs, dan lihat data pada table employees


Yap data yang sebelumnya kita hapus masih ada, perhatikan kolom deleted_at dimana jika kita melakukan operasi hapus data maka kolom deleted_at akan terisi dan ketika kita melakukan query select untuk mengambil semua data maka data yang diambil adalah data yang kolom deleted_at bernilai NULL.

Lalu bagaimana bang jika kita ingin menghapus permanen data kita ?

Yap caranya cukup mudah tinggal kita menggunakan method forceDelete()

<?php

namespace Tests\Feature;

use App\Models\Employee;
use Database\Seeders\EmployeeSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;

class SoftDeleteTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        DB::delete('DELETE FROM employees');
    }

    // unit test softDelete
    public function testDelete()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // delete
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->delete();

        // ambil semua data employee
        $employees = Employee::all();
        self::assertCount(1, $employees);
    }

    // unit test forceDelete (Hapus data permanen)
    public function testForceDelete()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // force delete (delete permanen)
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->forceDelete();

        // ambil semua data employee
        $employees = Employee::all();
        self::assertCount(1, $employees);
    }
}



perhatikan method testForceDelete, dan sobs-sobs silahkan buka PHPMyAdminnya


Yap data sruputkode sudah hilang permanen.

Lalu gimana bang caranya kita ambil semua data baik itu yang sudah terhapus softdelete dengan yang belum terhapus ?

Tenang sobs-sobs kita tinggal menggunakan method withTrashed(). artinya data yang sebelumnya kita lakukan operasi softDelete juga akan ikut terambil. perhatikan method testWithTrashed() sobs


<?php

namespace Tests\Feature;

use App\Models\Employee;
use Database\Seeders\EmployeeSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;

class SoftDeleteTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        DB::delete('DELETE FROM employees');
    }

    // unit test softDelete
    public function testDelete()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // delete
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->delete();

        // ambil semua data employee
        $employees = Employee::all();
        self::assertCount(1, $employees);
    }

    // unit test forceDelete (Hapus data permanen)
    public function testForceDelete()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // force delete (delete permanen)
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->forceDelete();

        // ambil semua data employee
        $employees = Employee::all();
        self::assertCount(1, $employees);
    }

    // unit test withTrashed (Ambil semua data)
    public function testWithTrashed()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

         // delete
         $sruputkode = Employee::where('name', 'sruputkode')->first();
         $sruputkode->delete();

        //  query semua data termasuk sudah dihapus (softdelete)
        $employees = Employee::withTrashed()->get();
        self::assertCount(2, $employees);


    }
}


Selanjutnya bagaimana bang kalo ingin ambil data yang sudah dihapus saja / softdelete ?

Uppssss kita tinggal menggunakan method onlyTrashed(). method ini akan mengembalikan hanya data yang sudah kita lakukan operasi softdelete sobs-sobs. perhatikan method testOnlyTrashed() sobs


<?php

namespace Tests\Feature;

use App\Models\Employee;
use Database\Seeders\EmployeeSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;

class SoftDeleteTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        DB::delete('DELETE FROM employees');
    }

    // unit test softDelete
    public function testDelete()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // delete
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->delete();

        // ambil semua data employee
        $employees = Employee::all();
        self::assertCount(1, $employees);
    }

    // unit test forceDelete (Hapus data permanen)
    public function testForceDelete()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // force delete (delete permanen)
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->forceDelete();

        // ambil semua data employee
        $employees = Employee::all();
        self::assertCount(1, $employees);
    }

    // unit test withTrashed (Ambil semua data)
    public function testWithTrashed()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // delete
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->delete();

        //  query semua data termasuk sudah dihapus (softdelete)
        $employees = Employee::withTrashed()->get();
        self::assertCount(2, $employees);
    }

    // unit test onlyTrashed (Ambil semua data hanya softdelete)
    public function testOnlyTrashed()
    {
        // seed
        $this->seed(EmployeeSeeder::class);

        // delete
        $sruputkode = Employee::where('name', 'sruputkode')->first();
        $sruputkode->delete();

        //  query semua data yang hanya dihapus (softdelete)
        $employees = Employee::onlyTrashed()->get();
        dump($employees);
        self::assertCount(1, $employees);
    }
}


Kesimpulan : 
Jika kita mengimplementasikan soft delete dilaravel maka method dibawah ini
- delete() : melakukan operasi soft delete
- forceDelete() : menghapus data secara permanen
- withTrashed() : ambil semua data termasuk data yang sudah dilakukan operasi softdelete
- onlyTrashed() : ambil semua data hanya data softdelete

Oke mungkin sekian dahulu sobs-sobs sekalian yang bisa gua sampaikan, jika sobs-sobs kurang jelas silahkan bertanya dikolom komentar atau dengan mencari refrensi ditempat lain.

See you next time.

Posting Komentar untuk "Mengenal apa itu soft delete di laravel"