Cara Menggunakan Model Observer di Laravel

Pernahkah kamu perlu menjalankan kode tertentu setiap kali sebuah model disimpan, diperbarui, atau dihapus? Misalnya, membuat log aktivitas otomatis, mengirim notifikasi, atau memb...

Cara Menggunakan Model Observer di Laravel

Pernahkah kamu perlu menjalankan kode tertentu setiap kali sebuah model disimpan, diperbarui, atau dihapus? Misalnya, membuat log aktivitas otomatis, mengirim notifikasi, atau membersihkan cache. Cara naif adalah menulisnya di setiap controller, tapi ini melanggar prinsip DRY (Don't Repeat Yourself). Solusinya adalah Model Observer โ€” sebuah kelas yang "mengawasi" lifecycle event Eloquent dan bereaksi secara otomatis.

Apa itu Eloquent Events?

Eloquent memicu event-event berikut selama lifecycle sebuah model:

  • creating / created โ€” sebelum dan sesudah INSERT.
  • updating / updated โ€” sebelum dan sesudah UPDATE.
  • saving / saved โ€” sebelum dan sesudah CREATE atau UPDATE.
  • deleting / deleted โ€” sebelum dan sesudah DELETE.
  • restoring / restored โ€” untuk soft delete, sebelum dan sesudah restore.
  • retrieved โ€” setelah model diambil dari database.

Membuat Observer

Buat observer menggunakan Artisan:

php artisan make:observer ProductObserver --model=Product

File akan dibuat di app/Observers/ProductObserver.php:

<?php

namespace App\Observers;

use App\Models\Product;
use Illuminate\Support\Facades\Log;

class ProductObserver
{
    public function creating(Product $product): void
    {
        // Otomatis isi slug sebelum disimpan
        if (empty($product->slug)) {
            $product->slug = \Str::slug($product->name);
        }
    }

    public function created(Product $product): void
    {
        Log::info("Produk baru dibuat: {$product->name} (ID: {$product->id})");
    }

    public function updating(Product $product): void
    {
        // Update slug jika nama berubah
        if ($product->isDirty('name')) {
            $product->slug = \Str::slug($product->name);
        }
    }

    public function updated(Product $product): void
    {
        // Bersihkan cache terkait produk ini
        cache()->forget("product_{$product->id}");
        Log::info("Produk diperbarui: {$product->name}");
    }

    public function deleting(Product $product): void
    {
        // Hapus semua gambar terkait sebelum produk dihapus
        foreach ($product->images as $image) {
            \Storage::disk('public')->delete($image->path);
            $image->delete();
        }
    }

    public function deleted(Product $product): void
    {
        Log::warning("Produk dihapus: {$product->name} (ID: {$product->id})");
    }
}

Mendaftarkan Observer

Ada dua cara mendaftarkan observer. Cara pertama adalah menggunakan attribute #[ObservedBy] langsung di model (Laravel 10.22+):

<?php

namespace App\Models;

use App\Observers\ProductObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Model;

#[ObservedBy([ProductObserver::class])]
class Product extends Model
{
    protected $fillable = ['name', 'slug', 'price', 'stock'];
}

Cara kedua adalah mendaftarkan di AppServiceProvider:

<?php

namespace App\Providers;

use App\Models\Product;
use App\Observers\ProductObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Product::observe(ProductObserver::class);
    }
}

Contoh Nyata: Activity Log Otomatis

Buat observer untuk mencatat semua perubahan data User ke tabel activity log:

<?php

namespace App\Observers;

use App\Models\ActivityLog;
use App\Models\User;

class UserObserver
{
    public function created(User $user): void
    {
        $this->log('created', $user, null, $user->toArray());
    }

    public function updated(User $user): void
    {
        $this->log('updated', $user, $user->getOriginal(), $user->getChanges());
    }

    public function deleted(User $user): void
    {
        $this->log('deleted', $user, $user->toArray(), null);
    }

    private function log(string $event, User $user, ?array $before, ?array $after): void
    {
        ActivityLog::create([
            'user_id'    => auth()->id(),
            'model_type' => User::class,
            'model_id'   => $user->id,
            'event'      => $event,
            'before'     => $before ? json_encode($before) : null,
            'after'      => $after  ? json_encode($after)  : null,
        ]);
    }
}

Menonaktifkan Observer Sementara

Terkadang kamu perlu menonaktifkan observer, misalnya saat seeder atau proses bulk import:

// Nonaktifkan observer untuk satu blok kode
Product::withoutObservers(function () {
    Product::factory()->count(1000)->create();
});

// Atau nonaktifkan observer tertentu saja
Product::withoutObservers([ProductObserver::class], function () {
    Product::factory()->count(1000)->create();
});

Menggunakan isDirty() dan getChanges()

Di dalam observer, kamu bisa mengecek kolom mana yang berubah:

public function updating(Product $product): void
{
    // Cek apakah kolom tertentu berubah
    if ($product->isDirty('price')) {
        $oldPrice = $product->getOriginal('price');
        $newPrice = $product->price;
        // Kirim notifikasi perubahan harga ke subscriber
    }

    // Lihat semua perubahan
    $changes = $product->getDirty();
    // ['price' => 15000, 'stock' => 20]
}

Kesimpulan

Model Observer adalah pola yang sangat bersih untuk memisahkan side effects dari logic bisnis utama. Alih-alih menyebar kode logging, cache clearing, atau notifikasi di seluruh controller, cukup daftarkan satu observer dan semua itu akan berjalan otomatis. Ini membuat kode lebih mudah ditest dan dipelihara. Gunakan observer setiap kali kamu menemukan pola berulang yang bereaksi terhadap perubahan model.

model observer laravel laravel observer eloquent observer event model laravel laravel creating updating deleting observer pattern laravel
Bagikan artikel
Kembali

Komentar (0)

Punya pertanyaan atau tambahan? Tulis di bawah โ€” tak perlu login.

Membalas komentarโ€ฆ batal

Belum ada komentar. Jadilah yang pertama!

๐Ÿš€ Partner Recommendation

Butuh Source Code & Aplikasi Premium?

Download aplikasi Laravel, POS, Sekolah, Klinik, ERP, dan source code siap pakai di GudangCode.

GudangCode
  • โœ” Source Code Premium
  • โœ” Sistem Siap Pakai
  • โœ” Lifetime Update
  • โœ” Membership Lifetime
  • โœ” Update Aplikasi Harian
Daftar Membership โ†’