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:

AspekMailableNotification
TargetAlamat email (string/user)Entitas notifiable (biasanya user)
ChannelEmail sajaBanyak channel sekaligus
PenyimpananTidak adaDatabase channel menyimpan riwayat
Contoh kasusFaktur 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:

bash
php artisan make:notification OrderPaid

Output yang Dihasilkan:

text

   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:

php
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:

  1. 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'].
  2. toMail() — mengembalikan MailMessage, builder pesan khusus notifikasi dengan ->line(), ->action(), dan ->greeting(). Kita bedah penuh di chapter Mail Notifications .
  3. toArray() — mengembalikan array yang akan disimpan sebagai kolom data di 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:

ChannelStatusPeran
databaseBawaanSimpan payload di tabel notifications
mailBawaanKirim versi email dari notifikasi
broadcastBawaanSiarkan event lewat broadcasting
slackPaket laravel/slack-notification-channelPost ke channel Slack
vonagePaket laravel/vonage-notification-channelSMS
telegram, dll.Paket komunitasLainnya

Runner berikut membuktikan tiga channel bawaan benar-benar terdaftar di ChannelManager aplikasi sandbox — tanpa satu pun paket tambahan terpasang:

php
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:

text
mail: Illuminate\Notifications\Channels\MailChannel
database: Illuminate\Notifications\Channels\DatabaseChannel
broadcast: Illuminate\Notifications\Channels\BroadcastChannel

Routing: 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:

php
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:

php
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:

text
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:

php
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:

php
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:

text
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 .