Advanced Laravel

Advanced Notifications & Broadcasting

15 min Lesson 28 of 40

Advanced Notifications & Broadcasting

Laravel's notification system provides a unified API for sending notifications across multiple channels. Combined with broadcasting, you can create real-time, interactive applications that keep users informed through their preferred communication channels.

Available Channels: Database, Mail, Broadcast, SMS (Vonage/Twilio), Slack, Discord, and custom channels. You can send a single notification to multiple channels simultaneously.

Custom Notification Channels

Creating custom channels allows you to send notifications through any service:

<?php // app/Notifications/Channels/WhatsAppChannel.php namespace App\Notifications\Channels; use Illuminate\Notifications\Notification; class WhatsAppChannel { public function send($notifiable, Notification $notification) { // Get the message from notification $message = $notification->toWhatsApp($notifiable); // Send via WhatsApp API $phoneNumber = $notifiable->routeNotificationFor('whatsapp', $notification); Http::post('https://api.whatsapp.com/send', [ 'phone' => $phoneNumber, 'message' => $message->content, 'media_url' => $message->mediaUrl ?? null, ]); } } // Create a notification class OrderShipped extends Notification { protected $order; public function __construct($order) { $this->order = $order; } public function via($notifiable) { return ['whatsapp', 'database', 'mail']; } public function toWhatsApp($notifiable) { return (object) [ 'content' => "Your order #{$this->order->id} has been shipped!", 'mediaUrl' => $this->order->tracking_image_url, ]; } public function toDatabase($notifiable) { return [ 'order_id' => $this->order->id, 'tracking_number' => $this->order->tracking_number, 'message' => 'Your order has been shipped', ]; } } // User model public function routeNotificationForWhatsApp($notification) { return $this->whatsapp_number; } // Send notification $user->notify(new OrderShipped($order));

Database Notifications

Store notifications in the database for in-app notification centers:

<?php // Migration: php artisan notifications:table // php artisan migrate // Notification with database channel class CommentReceived extends Notification { protected $comment; public function via($notifiable) { return ['database']; } public function toDatabase($notifiable) { return [ 'comment_id' => $this->comment->id, 'post_id' => $this->comment->post_id, 'author' => $this->comment->author->name, 'message' => $this->comment->author->name . ' commented on your post', 'action_url' => route('posts.show', $this->comment->post_id), ]; } } // Retrieve notifications in controller class NotificationController extends Controller { public function index() { $notifications = auth()->user() ->notifications() ->paginate(20); return view('notifications.index', compact('notifications')); } public function unread() { $unreadNotifications = auth()->user() ->unreadNotifications() ->get(); return response()->json($unreadNotifications); } public function markAsRead($id) { $notification = auth()->user() ->notifications() ->findOrFail($id); $notification->markAsRead(); return redirect($notification->data['action_url']); } public function markAllAsRead() { auth()->user()->unreadNotifications->markAsRead(); return response()->json(['message' => 'All notifications marked as read']); } }
Notification Center UI: Display unread count in your navigation using `auth()->user()->unreadNotifications->count()`. Use real-time updates with broadcasting to show new notifications instantly.

Broadcast Notifications

Send real-time notifications using Laravel Echo and WebSockets:

<?php // Install broadcasting support // composer require pusher/pusher-php-server // npm install --save-dev laravel-echo pusher-js // config/broadcasting.php 'connections' => [ 'pusher' => [ 'driver' => 'pusher', 'key' => env('PUSHER_APP_KEY'), 'secret' => env('PUSHER_APP_SECRET'), 'app_id' => env('PUSHER_APP_ID'), 'options' => [ 'cluster' => env('PUSHER_APP_CLUSTER'), 'encrypted' => true, ], ], ], // Notification with broadcast channel class NewMessage extends Notification implements ShouldBroadcast { use Queueable; protected $message; public function via($notifiable) { return ['database', 'broadcast']; } public function toDatabase($notifiable) { return [ 'message_id' => $this->message->id, 'sender' => $this->message->sender->name, 'preview' => Str::limit($this->message->content, 50), ]; } public function toBroadcast($notifiable) { return new BroadcastMessage([ 'message_id' => $this->message->id, 'sender' => [ 'id' => $this->message->sender->id, 'name' => $this->message->sender->name, 'avatar' => $this->message->sender->avatar_url, ], 'content' => $this->message->content, 'created_at' => $this->message->created_at->toISOString(), ]); } public function broadcastType() { return 'message.new'; } } // Frontend with Laravel Echo (resources/js/bootstrap.js) import Echo from 'laravel-echo'; import Pusher from 'pusher-js'; window.Pusher = Pusher; window.Echo = new Echo({ broadcaster: 'pusher', key: import.meta.env.VITE_PUSHER_APP_KEY, cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, forceTLS: true }); // Listen for notifications Echo.private(`App.Models.User.${userId}`) .notification((notification) => { console.log('New notification:', notification); // Show toast notification showNotification(notification.sender.name, notification.content); // Update unread count updateUnreadCount(); // Play notification sound playNotificationSound(); });

Advanced Notification Formatting

<?php // Rich mail notifications with actions class InvoicePaid extends Notification { use Queueable; protected $invoice; public function toMail($notifiable) { return (new MailMessage) ->subject('Invoice Paid') ->greeting('Hello '.$notifiable->name.',') ->line('Your invoice #'.$this->invoice->id.' has been paid.') ->lineIf($this->invoice->hasDiscount(), 'A discount of $'.$this->invoice->discount.' was applied.') ->action('View Invoice', url('/invoices/'.$this->invoice->id)) ->line('Thank you for your business!') ->attach(storage_path('invoices/'.$this->invoice->pdf_file), [ 'as' => 'invoice.pdf', 'mime' => 'application/pdf', ]); } } // Conditional channels based on user preferences class SystemAlert extends Notification { public function via($notifiable) { $channels = ['database']; if ($notifiable->prefers_email) { $channels[] = 'mail'; } if ($notifiable->prefers_sms) { $channels[] = 'vonage'; } if ($notifiable->is_online) { $channels[] = 'broadcast'; } return $channels; } } // Throttled notifications (prevent spam) class RateLimitedNotification extends Notification { public function shouldSend($notifiable, $channel) { // Only send email once per hour if ($channel === 'mail') { return Cache::add( 'notification:'.$notifiable->id.':'.$channel, true, now()->addHour() ); } return true; } }
Broadcasting Security: Always use private or presence channels for user-specific notifications. Never broadcast sensitive information on public channels. Implement proper authorization in your broadcasting routes.

On-Demand Notifications

Send notifications to non-users (guests, external parties):

<?php use Illuminate\Support\Facades\Notification; // Send to email address without user model Notification::route('mail', 'guest@example.com') ->route('vonage', '5555555555') ->notify(new OrderConfirmation($order)); // Send to multiple recipients Notification::route('mail', [ 'support@example.com', 'admin@example.com', ])->notify(new SystemAlert($issue)); // With Slack webhook Notification::route('slack', env('SLACK_WEBHOOK_URL')) ->notify(new DeploymentCompleted($deployment)); // Custom notification class for on-demand class GuestPasswordReset extends Notification { protected $token; public function via($notifiable) { return ['mail']; } public function toMail($notifiable) { $email = $notifiable->routes['mail']; return (new MailMessage) ->subject('Password Reset Request') ->line('You requested a password reset.') ->action('Reset Password', url('reset-password/'.$this->token)) ->line('If you did not request this, please ignore this email.'); } }
Exercise 1: Build a notification center with unread badges, mark as read functionality, and real-time updates using broadcasting. Include filtering by notification type and a "mark all as read" button.
Exercise 2: Create a custom Telegram notification channel. Implement a TelegramChannel class that sends messages via the Telegram Bot API. Send order updates through both email and Telegram.
Exercise 3: Implement a notification preference system where users can choose which channels they want to receive notifications on. Create a settings page with toggles for email, SMS, and push notifications for different event types.