Mendekouple logika dengan events & listeners, mengirim notifikasi lewat mail/SMS/database, dan me-broadcast event secara real-time dengan Laravel Reverb di Laravel 13.

Ketika sebuah post dipublikasikan, banyak hal yang harus terjadi: mengirim notifikasi ke subscriber, memutakhirkan indeks pencarian, memberi badge ke penulis, mengirim email ke admin. Jika semua ditulis berjejer di controller, controller jadi raksasa yang sulit dipelihara — dan setiap tambahan fitur berarti menyentuh kode lama yang berisiko.
Events & Listeners memecahkan ini dengan pola publish-subscribe: controller cukup me-dispatch satu event ("post dipublikasikan"), dan listener-listener yang tertarik menanganinya. Controller tidak perlu tahu siapa saja yang "mendengarkan".
Generate keduanya sekaligus:
php artisan make:event PostPublished
php artisan make:listener NotifySubscribers --event=PostPublished<?php
namespace App\Events;
use App\Models\Post;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PostPublished
{
use Dispatchable, SerializesModels;
public function __construct(
public Post $post,
) {
}
}<?php
namespace App\Listeners;
use App\Events\PostPublished;
class NotifySubscribers
{
public function handle(PostPublished $event): void
{
$subscribers = $event->post->author->followers;
foreach ($subscribers as $subscriber) {
$subscriber->notify(new PostPublishedNotification($event->post));
}
}
}Daftarkan pasangan event-listener di AppServiceProvider (atau gunakan Event::listen):
protected $listen = [
PostPublished::class => [
NotifySubscribers::class,
IndexInSearchEngine::class,
],
];Di controller, cukup satu baris:
use App\Events\PostPublished;
event(new PostPublished($post));Laravel secara otomatis menemukan listener yang ber-handle(Event $event) di folder app/Listeners (auto-discovery). Jika listener harus jalan di background, implementasikan ShouldQueue pada listener — Laravel akan menjadwalkannya sebagai job di queue (episode 14):
use Illuminate\Contracts\Queue\ShouldQueue;
class NotifySubscribers implements ShouldQueue
{
// handle() akan dieksekusi oleh worker
}Notifications adalah layer di atas events untuk mengirim pesan ke user lewat banyak kanal. Buat notification:
php artisan make:notification PostPublishedNotification<?php
namespace App\Notifications;
use App\Models\Post;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class PostPublishedNotification extends Notification
{
public function __construct(
public Post $post,
) {
}
public function via(object $notifiable): array
{
return ['mail', 'database']; // kirim via email + simpan di DB
}
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Post baru telah terbit')
->line("Post \"{$this->post->title}\" telah dipublikasikan.")
->action('Baca Sekarang', route('posts.show', $this->post));
}
public function toDatabase(object $notifiable): array
{
return [
'post_id' => $this->post->id,
'title' => $this->post->title,
];
}
}Model User harus memakai trait Notifiable:
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
}Kirim dan baca notifikasi:
$user->notify(new PostPublishedNotification($post));
$user->notifications; // koleksi
$user->unreadNotifications; // yang belum dibaca
$user->unreadNotifications->count();
$notification->markAsRead();Kanal database memerlukan tabel notifications:
php artisan notifications:table
php artisan migrateSelain mail dan database, kanal lain tersedia: sms (Via Vonage), slack, broadcast (real-time, episode 19), dan custom channel.
Tip
Kombinasikan events dengan notifications: event mewakili kejadian, notification mewakili pesan ke user. Satu event PostPublished bisa memicu beberapa notification ke user yang berbeda-beda — controller tetap satu baris event(...).
Broadcasting menyiarkan event ke browser via WebSocket sehingga halaman berubah tanpa reload. Event yang di-broadcast mengimplementasikan ShouldBroadcast:
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class PostPublished implements ShouldBroadcast
{
public function broadcastOn(): Channel
{
return new Channel('posts');
}
}Server Laravel memerlukan broadcaster — sejak Laravel 13, Reverb adalah WebSocket server bawaan (detail penuh di episode 19). Dengan Reverb + Echo, notifikasi database bisa tampil real-time di UI tanpa refresh.
Inti yang harus dibawa pulang:
ShouldQueue membuat listener berjalan di background.Di episode 16 selanjutnya kita akan membahas security: CSRF, XSS & middleware — middleware global vs route middleware, custom middleware, token @csrf, escape output Blade, sanitasi input, serta TrustProxies dan VerifyCsrfToken. Sampai jumpa di episode 16!