Laravel Events dan Listeners di 2026: Arsitektur Event-Driven dan Pertanyaan Wawancara

Panduan lengkap tentang Laravel events dan listeners untuk arsitektur event-driven. Pelajari observer pattern, queued listeners, event subscribers, dan pertanyaan wawancara teknis.

Laravel Events dan Listeners - Arsitektur Event-Driven

Laravel events dan listeners mengimplementasikan observer pattern, memisahkan komponen dengan membiarkan bagian aplikasi bereaksi terhadap aksi tanpa dependensi langsung. Ketika pengguna melakukan pemesanan, event OrderShipped dipicu, dan listener terpisah menangani notifikasi, analitik, dan pembaruan inventaris secara independen.

Laravel 12 Event Discovery

Laravel 12 secara otomatis menemukan listener di app/Listeners. Setiap kelas dengan method handle atau __invoke yang memiliki type-hint ke kelas event akan terdaftar secara otomatis, tanpa perlu file konfigurasi.

Cara Kerja Event Discovery di Laravel 12

Sejak Laravel 11, EventServiceProvider dihapus. Laravel memindai direktori Listeners dan menggunakan reflection untuk menentukan event mana yang ditangani setiap listener berdasarkan type hint pada signature method handle.

app/Listeners/SendOrderConfirmation.phpphp
<?php

namespace App\Listeners;

use App\Events\OrderShipped;

class SendOrderConfirmation
{
    public function handle(OrderShipped $event): void
    {
        // Kirim email konfirmasi ke $event->order->user
    }
}

Listener di atas terdaftar secara otomatis untuk event OrderShipped. Tidak perlu binding manual di service provider. Hal ini mengurangi boilerplate dan menjaga hubungan event-listener tetap dekat dengan kode yang mengimplementasikannya.

Untuk memverifikasi listener yang terdaftar, jalankan php artisan event:list. Untuk production, cache manifest event dengan php artisan event:cache untuk melewatkan pemindaian direktori pada setiap request.

Membuat Events dan Listeners dengan Artisan

Laravel menyediakan perintah Artisan untuk membuat scaffold events dan listeners:

bash
# Generate kelas event
php artisan make:event OrderShipped

# Generate listener yang terhubung ke event
php artisan make:listener SendShipmentNotification --event=OrderShipped

Kelas event yang dihasilkan menggunakan tiga trait: Dispatchable untuk method static dispatch(), InteractsWithSockets untuk broadcasting, dan SerializesModels untuk serialisasi model Eloquent ketika listener di-queue.

app/Events/OrderShipped.phpphp
<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Queue\SerializesModels;

class OrderShipped
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(
        public Order $order,
    ) {}
}

Kelas event adalah container data. Ia menyimpan model Order dan tidak ada yang lain. Business logic berada di listener, bukan di event.

Dispatching Events dari Controllers dan Services

Dispatch event menggunakan method static dispatch() pada kelas event:

app/Http/Controllers/OrderController.phpphp
<?php

namespace App\Http\Controllers;

use App\Events\OrderShipped;
use App\Models\Order;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function ship(Request $request, Order $order)
    {
        // Logika pengiriman di sini...
        
        OrderShipped::dispatch($order);
        
        return redirect()->route('orders.index');
    }
}

Untuk dispatch kondisional, gunakan dispatchIf() atau dispatchUnless():

php
// Hanya dispatch jika order memiliki nomor tracking
OrderShipped::dispatchIf($order->tracking_number !== null, $order);

Siap menguasai wawancara Laravel Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Queued Listeners untuk Operasi Lambat

Listener yang mengirim email, memanggil API eksternal, atau melakukan komputasi berat harus berjalan secara asinkron. Implementasikan ShouldQueue untuk mendorong listener ke queue:

app/Listeners/SendShipmentNotification.phpphp
<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    public $queue = 'notifications';
    public $delay = 60; // Tunggu 60 detik sebelum memproses

    public function handle(OrderShipped $event): void
    {
        // Kirim notifikasi ke $event->order->user
    }
}

Kustomisasi koneksi dan nama queue dengan properti $connection dan $queue, atau gunakan method runtime:

php
public function viaConnection(): string
{
    return 'redis';
}

public function viaQueue(): string
{
    return $this->event->order->priority === 'high' 
        ? 'high-priority' 
        : 'default';
}

Conditional Queueing dengan shouldQueue

Terkadang listener hanya perlu di-queue berdasarkan data event:

php
public function shouldQueue(OrderShipped $event): bool
{
    // Hanya queue untuk pesanan di atas Rp 1.000.000
    return $event->order->total >= 1000000;
}

Transaksi Database dan Timing Event

Queued listener yang di-dispatch di dalam transaksi mungkin memproses sebelum transaksi commit, menyebabkan error data tidak ditemukan. Ada dua solusi:

1. Konfigurasi global di config/queue.php:

php
'connections' => [
    'redis' => [
        'after_commit' => true,
    ],
],

2. Per-listener dengan ShouldQueueAfterCommit:

php
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;

class UpdateInventory implements ShouldQueueAfterCommit
{
    public function handle(OrderShipped $event): void
    {
        // Aman untuk query order, transaksi sudah commit
    }
}

Untuk event itu sendiri, implementasikan ShouldDispatchAfterCommit pada kelas event:

php
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;

class OrderShipped implements ShouldDispatchAfterCommit
{
    // Event hanya dispatch setelah transaksi commit
}

Unique Listeners untuk Mencegah Duplikasi

Interface ShouldBeUnique mencegah listener duplikat masuk queue saat satu masih memproses:

php
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessLicenseKey implements ShouldQueue, ShouldBeUnique
{
    public $uniqueFor = 3600; // Lock kadaluarsa setelah 1 jam

    public function uniqueId(LicensePurchased $event): string
    {
        return 'license:' . $event->license->id;
    }

    public function handle(LicensePurchased $event): void
    {
        // Generate dan assign license key
    }
}

Jika license ID yang sama memicu beberapa event dengan cepat, hanya listener pertama yang memproses. Percobaan berikutnya menemukan lock masih dipegang dan melewatkan queueing.

Event Subscribers untuk Event Terkait

Ketika beberapa event terkait berbagi logika penanganan yang sama, event subscriber mengelompokkan handler dalam satu kelas:

app/Listeners/UserActivitySubscriber.phpphp
<?php

namespace App\Listeners;

use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;

class UserActivitySubscriber
{
    public function handleLogin(Login $event): void
    {
        // Log login berhasil, update timestamp last_login
    }

    public function handleLogout(Logout $event): void
    {
        // Log logout, hapus data sesi
    }

    public function subscribe(Dispatcher $events): array
    {
        return [
            Login::class => 'handleLogin',
            Logout::class => 'handleLogout',
        ];
    }
}

Subscriber mengikuti aturan automatic discovery. Jika method handler berada di kelas subscriber dengan parameter yang di-type-hint dengan benar, Laravel mendaftarkannya secara otomatis.

Mendengarkan Multiple Events dengan Union Types

Satu listener dapat merespons beberapa tipe event menggunakan PHP 8 union types:

php
public function handle(OrderShipped|OrderCancelled $event): void
{
    match (true) {
        $event instanceof OrderShipped => $this->notifyShipped($event),
        $event instanceof OrderCancelled => $this->notifyCancelled($event),
    };
}

Pola ini bekerja dengan baik untuk notifikasi yang mengikuti logika serupa di berbagai tipe event.

Laravel 12 memperkenalkan Event::defer() untuk menunda dispatch event sampai setelah blok kode selesai. Ini memastikan listener memiliki akses ke semua record terkait:

php
use Illuminate\Support\Facades\Event;

Event::defer(function () {
    $user = User::create(['name' => 'John']);
    $user->posts()->create(['title' => 'Welcome']);
});
// Event untuk pembuatan User dan Post dispatch di sini

Jika exception terjadi di dalam closure, event yang ditunda tidak akan pernah dispatch.

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Pertanyaan Wawancara tentang Laravel Events dan Listeners

Wawancara teknis sering menguji pemahaman arsitektur event-driven. Berikut adalah pertanyaan yang membedakan developer Laravel berpengalaman:

Q: Bagaimana Laravel 12 mendaftarkan event listener tanpa EventServiceProvider?

Laravel memindai app/Listeners menggunakan reflection. Ia membaca type hint pada method handle() atau __invoke() untuk menentukan event mana yang ditangani setiap listener. Cache manifest di production dengan php artisan event:cache.

Q: Kapan listener harus mengimplementasikan ShouldQueue?

Kapan pun operasi memakan waktu lebih dari beberapa milidetik: mengirim email, memanggil API eksternal, membuat laporan, atau memproses file. Listener sinkron memblokir respons HTTP.

Q: Masalah apa yang dipecahkan ShouldQueueAfterCommit?

Queued listener mungkin memproses sebelum transaksi database commit. Jika listener melakukan query untuk record yang baru dibuat, ia gagal karena data belum commit. ShouldQueueAfterCommit menunda dispatch queue sampai transaksi selesai.

Q: Bagaimana cara mencegah pemrosesan duplikat untuk event yang sama?

Implementasikan ShouldBeUnique. Definisikan uniqueId() untuk mengembalikan cache key berdasarkan data event. Listener mengakuisisi atomic lock, dan dispatch duplikat dilewati jika lock masih dipegang.

Q: Apa perbedaan antara event listener dan event subscriber?

Listener menangani satu tipe event. Subscriber adalah kelas yang mendaftarkan handler untuk beberapa event terkait di satu tempat, berguna untuk mengelompokkan event autentikasi atau audit logging.

Arti Laravel Events untuk Aplikasi Skalabel

  • Events memisahkan komponen, membiarkan fitur seperti notifikasi dan analitik berkembang secara independen
  • Queued listener memindahkan operasi lambat, menjaga respons HTTP tetap cepat
  • ShouldQueueAfterCommit mencegah race condition antara queue worker dan transaksi database
  • Automatic discovery di Laravel 12 menghilangkan overhead konfigurasi, menjaga logika listener dekat dengan implementasi
  • Event subscriber mengonsolidasikan penanganan event terkait, mengurangi penyebaran file untuk pola umum seperti tracking aktivitas pengguna
  • Modul /technologies/laravel/interview-questions/events-listeners di SharpSkill mencakup pola-pola ini dengan pertanyaan interaktif
Tantangan harian

Bisakah kamu menemukan bug di Laravel?

Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Anthony Fillion-Maillet

Ditulis oleh

Anthony Fillion-Maillet

Pendiri SharpSkill

Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.

Diperbarui 20 Agustus 2026

Tag

#laravel
#events
#listeners
#event-driven
#observer-pattern
#queue

Bagikan

Artikel terkait