Mailable yang kita bangun sejauh ini menjawab satu pertanyaan: “bagaimana email ini diformat?” Namun aplikasi nyata menghadapi pertanyaan yang berbeda: “bagaimana memberi tahu user Budi tentang kejadian X?” — dan jawabannya tidak selalu email. Budi mungkin ingin pesanan tersimpan di dalam aplikasi (channel database), diberi tahu lewat email (channel mail), atau menerima event realtime di dashboard (channel broadcast). Laravel Notification adalah sistem untuk pertanyaan kedua: satu class notifikasi yang menargetkan user lewat banyak channel sekaligus. Pada chapter ini kita pelajari kapan memilih Notification vs Mailable, anatomi class-nya, dan konsep routing yang menentukan alamat tujuan tiap channel.
Mailable atau Notification? #
Kedua sistem sama-sama mengirim pesan, tetapi menyelesaikan masalah berbeda:
| Aspek | Mailable | Notification |
|---|---|---|
| Target | Alamat email (string/user) | Entitas notifiable (biasanya user) |
| Channel | Email saja | Banyak channel sekaligus |
| Penyimpanan | Tidak ada | Database channel menyimpan riwayat |
| Contoh kasus | Faktur PDF, newsletter | “Pesanan dikirim”, “komentar baru” |
Aturan praktisnya: jika kontennya hanya email dan tidak perlu riwayat, Mailable cukup. Jika pesan berhubungan dengan aktivitas user dan mungkin perlu tampil di beberapa tempat sekaligus (bell icon aplikasi plus email), Notification lebih tepat. Keduanya juga bisa bekerja sama — notification menyimpan riwayat di database sambil mengirim email yang di dalamnya memakai template mailable.
Membuat Class Notification #
Perintah artisan menghasilkan kerangka class:
php artisan make:notification OrderPaidOutput yang Dihasilkan:
INFO Notification [app/Notifications/OrderPaid.php] created successfully. Class yang dihasilkan berisi tiga method inti: via() menentukan channel, toMail() memformat versi email, dan toArray() membentuk payload untuk channel yang menyimpan data (misalnya database). Kita isi dengan notifikasi pembayaran diterima:
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class OrderPaid extends Notification
{
use Queueable;
public function __construct(
public string $orderId,
public int $total,
) {}
public function via(object $notifiable): array
{
return ['database', 'mail'];
}
public function toMail(object $notifiable): MailMessage
{
$url = url('/pesanan/'.$this->orderId);
return (new MailMessage)
->subject('Pembayaran Pesanan #'.$this->orderId.' Diterima')
->greeting('Halo '.($notifiable->name ?? 'Pelanggan').'!')
->line('Pembayaran sebesar Rp'.number_format($this->total).' sudah kami terima.')
->action('Lihat Pesanan', $url)
->line('Pesanan akan segera kami proses dan dikirim.');
}
public function toArray(object $notifiable): array
{
return [
'order_id' => $this->orderId,
'total' => $this->total,
'pesan' => 'Pembayaran diterima.',
];
}
}Bedah per method:
via(object $notifiable): array— menerima entitas yang akan dinotifikasi dan mengembalikan daftar channel. Method ini dipanggil per-penerima, jadi logika bisa kondisional: user premium dapat['database', 'mail'], user biasa cukup['database'].toMail()— mengembalikanMailMessage, builder pesan khusus notifikasi dengan->line(),->action(), dan->greeting(). Kita bedah penuh di chapter Mail Notifications .toArray()— mengembalikan array yang akan disimpan sebagai kolomdatadi tabel notifications untuk channel database (chapter Database Notifications ).
Channel yang Tersedia di Laravel 13 #
Framework membawa tiga channel di paket inti; sisanya lewat paket resmi terpisah:
| Channel | Status | Peran |
|---|---|---|
database | Bawaan | Simpan payload di tabel notifications |
mail | Bawaan | Kirim versi email dari notifikasi |
broadcast | Bawaan | Siarkan event lewat broadcasting |
slack | Paket laravel/slack-notification-channel | Post ke channel Slack |
vonage | Paket laravel/vonage-notification-channel | SMS |
telegram, dll. | Paket komunitas | Lainnya |
Runner berikut membuktikan tiga channel bawaan benar-benar terdaftar di ChannelManager aplikasi sandbox — tanpa satu pun paket tambahan terpasang:
use Illuminate\Notifications\ChannelManager;
$channels = ['mail', 'database', 'broadcast'];
foreach ($channels as $c) {
$driver = app(ChannelManager::class)->channel($c);
echo $c . ': ' . get_class($driver) . "\n";
}Output yang Dihasilkan:
mail: Illuminate\Notifications\Channels\MailChannel
database: Illuminate\Notifications\Channels\DatabaseChannel
broadcast: Illuminate\Notifications\Channels\BroadcastChannelRouting: Menentukan Alamat Tiap Channel #
Setiap channel perlu tahu alamat tujuan. Method routeNotificationFor($driver) pada entitas notifiable — disediakan trait RoutesNotifications yang dipakai model User — memetakan nama channel ke alamat. Logikanya di dalam framework:
public function routeNotificationFor($driver, $notification = null)
{
if (method_exists($this, $method = 'routeNotificationFor'.Str::studly($driver))) {
return $this->{$method}($notification);
}
return match ($driver) {
'database' => $this->notifications(),
'mail' => $this->email,
default => null,
};
}Dua jalur terlihat jelas. Jalur pertama: jika model punya method routeNotificationForMail() sendiri, method itu menang. Jalur kedua (default): channel mail memakai kolom email, dan channel database memakai relasi notifications(). Kita verifikasi keduanya dengan runner:
use App\Models\User;
use App\Notifications\OrderPaid;
$user = User::create([
'name' => 'Budi',
'email' => '[email protected]',
'password' => bcrypt('rahasia-kursus'),
]);
$notif = new OrderPaid('123', 775000);
echo 'channels_via: ' . implode(', ', $notif->via($user)) . "\n";
echo 'routes_mail: ' . $user->routeNotificationFor('mail') . "\n";
echo 'routes_database: ' . json_encode($user->routeNotificationFor('database')) . "\n";Output yang Dihasilkan:
channels_via: database, mail
routes_mail: [email protected]
routes_database: {}routes_mail menunjukkan email Budi diambil otomatis dari kolom email. Nilai routes_database berupa objek relasi — cukup hadir sebagai bukti bahwa channel database punya jalur routing sendiri tanpa alamat eksplisit. Untuk channel lain, kita bisa menimpa per model:
class User extends Authenticatable
{
public function routeNotificationForMail(object $notification): array|string
{
// arahkan semua email notifikasi ke alamat khusus
return [$this->email => $this->name];
}
}Method ini dipanggil routeNotificationFor + nama channel dalam studly case — pola yang sama berlaku untuk routeNotificationForSlack(), routeNotificationForVonage(), dan seterusnya.
Kirim ke Banyak Penerima Sekaligus #
Facade Notification mengirim ke koleksi notifiable dalam satu panggilan:
use App\Models\User;
use App\Notifications\OrderPaid;
use Illuminate\Support\Facades\Notification;
Notification::send([$siti], new OrderPaid('500', 99000));
echo 'notifikasi_siti: ' . $siti->notifications->count() . "\n";
echo 'data: ' . json_encode($siti->notifications->first()->data) . "\n";Output yang Dihasilkan:
notifikasi_siti: 1
data: {"order_id":"500","total":99000,"pesan":"Pembayaran diterima."}Satu class, dua channel aktif — dan kita langsung melihat channel database bekerja: data berisi persis array dari toArray(). Itulah pembahasan lengkap chapter Database Notifications
. Konsep lengkap sistem notifikasi bisa dirujuk di dokumentasi Notifications
.