Queueable notifications
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():
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
// 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