0

Queueable notifications

Intermediate5 min read·lv-21-004

Concept

Custom notification channels allow sending notifications through any transport — Telegram, FCM (Firebase push), Twilio SMS, Slack, Pushover — by implementing the Channel contract.

Channel contract: Illuminate\Notifications\Channels\Channel is NOT the contract to implement. Instead, a custom channel is any class with a send(mixed $notifiable, Notification $notification): void method. No interface required — duck typing.

Registering: Channels are resolved from the container. Return the channel class name string from via():

php
public function via(): array { return [\App\Channels\TelegramChannel::class]; }

Laravel resolves it via the container and calls ->send($notifiable, $this).

Notification-to-channel format method: Convention is toTelegram($notifiable), toSlack($notifiable), etc. The channel's send() method calls this on the notification. Not enforced — just a convention.

Notification::extend(string $driver, callable $callback): Register a channel by driver name string so you can use via(['telegram']) instead of the class name.

Community channels: laravel-notification-channels.com — hundreds of community channels including Telegram, Twilio, Vonage, Discord, PagerDuty, Pushover.

Code Example

php
<?php
// Custom Telegram channel
namespace App\Channels;

use Illuminate\Notifications\Notification;

class TelegramChannel
{
    public function __construct(private readonly \App\Services\TelegramBot $telegram) {}

    public function send(mixed $notifiable, Notification $notification): void
    {
        // Get the Telegram message from the notification
        if (!method_exists($notification, 'toTelegram')) return;
        $message = $notification->toTelegram($notifiable);

        // Get the chat ID for this user
        $chatId = $notifiable->routeNotificationForTelegram();
        if (!$chatId) return;

        $this->telegram->sendMessage($chatId, $message);
    }
}

// Notification using the custom channel
class CriticalAlert extends \Illuminate\Notifications\Notification
{
    public function __construct(private readonly string $message) {}

    public function via(object $notifiable): array
    {
        return [\App\Channels\TelegramChannel::class, 'mail'];
    }

    // Called by TelegramChannel::send()
    public function toTelegram(object $notifiable): string
    {
        return "🚨 ALERT: {$this->message}";
    }

    public function toMail(object $notifiable): \Illuminate\Notifications\Messages\MailMessage
    {
        return (new \Illuminate\Notifications\Messages\MailMessage)
            ->subject('Critical Alert')
            ->line($this->message);
    }
}

// User model — routing for custom channel
class User extends \Illuminate\Foundation\Auth\User
{
    use \Illuminate\Notifications\Notifiable;

    public function routeNotificationForTelegram(): ?string
    {
        return $this->telegram_chat_id;
    }
}

// Register channel as named driver (optional, for cleaner via() strings)
// In AppServiceProvider::boot():
\Illuminate\Support\Facades\Notification::extend('telegram', function($app) {
    return new \App\Channels\TelegramChannel($app->make(\App\Services\TelegramBot::class));
});
// Now can use: public function via() { return ['telegram', 'mail']; }

// Using community channels: laravel-notification-channels.com
// composer require laravel-notification-channels/telegram