Contoh Implementasi Observer di Laravel 12: Auto-Slug, Audit Trail, dan Cache
Artikel ini melanjutkan penjelasan konsep Observer di Laravel 12 dengan studi kasus implementasi lengkap: sistem audit trail dan auto-slug generation.
Studi Kasus 1: Auto-Slug Generation
Masalah umum: setiap kali artikel dibuat atau diupdate, slug harus di-generate dari title. Tanpa Observer, logika ini tersebar di berbagai controller.
Dengan Observer, cukup satu tempat:
<?php
namespace AppObservers;
use AppModelsArticle;
use IlluminateSupportStr;
class ArticleObserver
{
public function creating(Article $article): void
{
$article->slug = $this->generateUniqueSlug($article->title);
}
public function updating(Article $article): void
{
if ($article->isDirty('title')) {
$article->slug = $this->generateUniqueSlug($article->title, $article->id);
}
}
private function generateUniqueSlug(string $title, ?int $excludeId = null): string
{
$slug = Str::slug($title);
$query = Article::where('slug', $slug);
if ($excludeId) {
$query->where('id', '!=', $excludeId);
}
if (!$query->exists()) {
return $slug;
}
// Tambah angka kalau slug sudah ada
$counter = 1;
while (Article::where('slug', "{$slug}-{$counter}")
->when($excludeId, fn ($q) => $q->where('id', '!=', $excludeId))
->exists()) {
$counter++;
}
return "{$slug}-{$counter}";
}
}
Studi Kasus 2: Audit Trail Otomatis
Rekam semua perubahan pada model penting, berguna untuk compliance, debugging, atau fitur “lihat riwayat perubahan”:
<?php
namespace AppObservers;
use AppModelsArticle;
use AppModelsAuditLog;
class ArticleObserver
{
public function created(Article $article): void
{
$this->log('created', $article, [], $article->getAttributes());
}
public function updated(Article $article): void
{
$this->log('updated', $article, $article->getOriginal(), $article->getChanges());
}
public function deleted(Article $article): void
{
$this->log('deleted', $article, $article->getAttributes(), []);
}
private function log(string $action, Article $article, array $old, array $new): void
{
AuditLog::create([
'user_id' => auth()->id(),
'model_type' => Article::class,
'model_id' => $article->id,
'action' => $action,
'old_values' => $old,
'new_values' => $new,
'ip_address' => request()->ip(),
]);
}
}
Model AuditLog:
Schema::create('audit_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->string('model_type');
$table->unsignedBigInteger('model_id');
$table->string('action'); // created, updated, deleted
$table->json('old_values')->nullable();
$table->json('new_values')->nullable();
$table->string('ip_address')->nullable();
$table->timestamp('created_at');
$table->index(['model_type', 'model_id']);
});
Studi Kasus 3: Cache Invalidation
Cache artikel halaman statis dan harus di-clear saat artikel berubah:
<?php
namespace AppObservers;
use AppModelsArticle;
use IlluminateSupportFacadesCache;
class ArticleObserver
{
public function saved(Article $article): void
{
// Clear cache artikel individual
Cache::forget("article:{$article->id}");
Cache::forget("article:{$article->slug}");
// Clear cache daftar artikel
Cache::forget('articles:latest');
Cache::forget("articles:category:{$article->category_id}");
}
public function deleted(Article $article): void
{
Cache::forget("article:{$article->id}");
Cache::forget("article:{$article->slug}");
Cache::forget('articles:latest');
}
}
Studi Kasus 4: Observer dengan Multiple Models
Kalau beberapa model butuh audit trail yang sama, buat Observer yang reusable:
<?php
namespace AppObservers;
use AppModelsAuditLog;
class AuditableObserver
{
public function created($model): void
{
AuditLog::create([
'user_id' => auth()->id(),
'model_type' => get_class($model),
'model_id' => $model->id,
'action' => 'created',
'new_values' => $model->getAttributes(),
]);
}
public function updated($model): void
{
AuditLog::create([
'user_id' => auth()->id(),
'model_type' => get_class($model),
'model_id' => $model->id,
'action' => 'updated',
'old_values' => $model->getOriginal(),
'new_values' => $model->getChanges(),
]);
}
}
Register ke beberapa model sekaligus:
// Di AppServiceProvider
Article::observe(AuditableObserver::class);
Product::observe(AuditableObserver::class);
Order::observe(AuditableObserver::class);
Bypass Observer saat Seeding
<?php
namespace DatabaseSeeders;
use AppModelsArticle;
class ArticleSeeder extends Seeder
{
public function run(): void
{
// Bypass observer agar tidak trigger audit trail saat seeding
Article::withoutObservers(function () {
Article::factory(100)->create();
});
}
}
Baca Juga
Butuh tim yang bantu implementasi arsitektur yang clean di aplikasi Laravel? Lihat layanan pengembangan aplikasi kami.
Baca Juga
Artikel Lainnya di Kategori Laravel
10 November 2025
Contoh Implementasi Policy dan Gate di Laravel 12: Studi Kasus CMS Multi-Role
Artikel ini melanjutkan penjelasan konsep Policy dan Gate di Laravel 12 dengan studi kasus implementasi lengkap: sistem manajemen konten dengan beberapa level akses. Studi Kasus: Sistem CMS dengan Multi-Role Skenario: aplikasi CMS dengan role admin, editor, dan author. Aturannya: Admin bisa lakukan semua aksi di artikel mana saja Editor bisa buat, edit, dan publish artikel […]
Baca Artikel10 November 2025
Apa Itu Contract di Laravel 12? Penjelasan Simpel + Contoh Kode
Bayangkan Anda membangun fitur notifikasi. Hari ini kirim via email, bulan depan ditambah WhatsApp, tahun depan mungkin push notification. Kalau kode Anda langsung bergantung ke implementasi email spesifik, setiap perubahan akan memaksa Anda menyentuh banyak file sekaligus. Di sinilah Contract di Laravel 12 berguna. Apa Itu Contract di Laravel 12? Contract di Laravel adalah sekumpulan […]
Baca Artikel
Laravel 9 November 2025
Cara Install Laravel 12: Panduan Lengkap dari Instalasi sampai Project Jalan
Kamu baru mau mulai belajar Laravel 12 atau mau memulai project baru? Artikel ini memandu instalasi dari nol, mulai dari kebutuhan sistem, instalasi Laravel, sampai project pertama bisa jalan di browser. Tidak ada yang dilewati. Setiap perintah dijelaskan kenapa dijalankan, bukan sekadar disalin. Kebutuhan Sistem Sebelum Mulai Pastikan versi PHP dan tools berikut sudah terpasang: […]
Baca ArtikelIngin Membaca Artikel Lainnya?
Temukan lebih banyak insight dan tips tentang teknologi dan bisnis digital.
Lihat Semua Artikel