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
Laravel 9 November 2025
Invokable Controller di Laravel: Cara Kerja, Contoh Kode, dan Kapan Memakainya
Ada satu fitur Laravel yang sering dilewatkan developer pemula: invokable controller. Padahal kalau dipakai di tempat yang tepat, kode jadi lebih bersih dan lebih mudah dibaca. Artikel ini menjelaskan apa itu invokable controller, kapan sebaiknya dipakai, dan bagaimana cara implementasinya di Laravel 12. Apa Itu Invokable Controller? Invokable controller adalah controller yang hanya punya satu […]
Baca Artikel9 November 2025
Apa Itu Laravel Volt dan Bagaimana Cara Kerjanya
Kalau Anda pernah pakai Livewire di Laravel, mungkin sudah tahu betapa nyamannya bikin komponen reaktif tanpa harus tulis JavaScript. Laravel Volt membawa pengalaman itu selangkah lebih jauh dengan sintaks single-file component yang lebih bersih. Artikel ini menjelaskan apa itu Laravel Volt, bagaimana cara kerjanya, dan di mana Volt cocok dipakai. Apa Itu Laravel Volt? Laravel […]
Baca Artikel9 November 2025
Tutorial Laravel 12 Job Batching: Implementasi, Progress, dan Error Handling
Bayangkan Anda perlu kirim email ke 5.000 pengguna sekaligus, atau proses 1.000 gambar setelah upload. Kalau dijalankan satu per satu lewat queue biasa, Anda tidak tahu kapan semuanya selesai, dan tidak bisa jalankan aksi “setelah semua beres”. Job Batching di Laravel menyelesaikan masalah ini. Artikel ini membahas cara kerjanya, implementasi lengkap dengan contoh kode, dan […]
Baca ArtikelIngin Membaca Artikel Lainnya?
Temukan lebih banyak insight dan tips tentang teknologi dan bisnis digital.
Lihat Semua Artikel