Creating Notifications
Create multi-channel notifications that send via email and database.
Quick Start
Section titled “Quick Start”# Generate notification class./vendor/bin/sail artisan make:notification BookingConfirmedNotificationImplementation Steps
Section titled “Implementation Steps”1. Define Notification Class
Section titled “1. Define Notification Class”<?php
namespace App\Notifications;
use App\Models\Booking;use Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Notifications\Messages\MailMessage;use Illuminate\Notifications\Notification;
class BookingConfirmedNotification extends Notification implements ShouldQueue{ use Queueable;
public function __construct( public Booking $booking ) { }
public function via(object $notifiable): array { return ['mail', 'database']; }
public function toMail(object $notifiable): MailMessage { return (new MailMessage()) ->subject('Booking Confirmed: ' . $this->booking->reference) ->greeting('Hello ' . $notifiable->name . '!') ->line('Your booking has been confirmed.') ->line('**Reference:** ' . $this->booking->reference) ->action('View Booking', url('/admin/bookings/' . $this->booking->id)) ->line('Thank you for using Volare!'); }
public function toArray(object $notifiable): array { return [ 'title' => 'Booking Confirmed', 'message' => 'Booking ' . $this->booking->reference . ' confirmed.', 'booking_id' => $this->booking->id, 'reference' => $this->booking->reference, ]; }}2. Choose When to Send
Section titled “2. Choose When to Send”From Observer:
use App\Notifications\BookingConfirmedNotification;use Illuminate\Support\Facades\Notification;
public function updated(Booking $booking): void{ if ($booking->isDirty('status') && $booking->status === BookingStatus::Confirmed) { $user = $booking->user; $user->notify(new BookingConfirmedNotification($booking)); }}From Controller/Service:
$user->notify(new BookingConfirmedNotification($booking));To Multiple Users:
$users = User::role(Role::Admin->value)->get();Notification::send($users, new BookingConfirmedNotification($booking));3. Test the Notification
Section titled “3. Test the Notification”use Illuminate\Support\Facades\Notification;
it('sends notification when booking is confirmed', function (): void { Notification::fake();
$user = User::factory()->create(); $booking = Booking::factory()->create(['user_id' => $user->id]);
$booking->update(['status' => BookingStatus::Confirmed]);
Notification::assertSentTo($user, BookingConfirmedNotification::class);});
it('notification contains booking details', function (): void { Notification::fake();
$user = User::factory()->create(); $booking = Booking::factory()->create([ 'user_id' => $user->id, 'reference' => 'BK12345', ]);
$user->notify(new BookingConfirmedNotification($booking));
Notification::assertSentTo($user, BookingConfirmedNotification::class, function ($notification) use ($booking, $user) { $data = $notification->toArray($user); return $data['booking_id'] === $booking->id && $data['reference'] === 'BK12345'; });});
it('sends via mail and database channels', function (): void { Notification::fake();
$user = User::factory()->create(); $booking = Booking::factory()->create(['user_id' => $user->id]);
$user->notify(new BookingConfirmedNotification($booking));
Notification::assertSentTo($user, BookingConfirmedNotification::class, function ($notification, $channels) { return in_array('mail', $channels) && in_array('database', $channels); });});Best Practices
Section titled “Best Practices”Always Queue Notifications
Section titled “Always Queue Notifications”Implement ShouldQueue to prevent blocking:
class MyNotification extends Notification implements ShouldQueue{ use Queueable;}Queue worker must be running:
./vendor/bin/sail artisan queue:workUse Both Channels
Section titled “Use Both Channels”Always provide mail and database channels:
public function via(object $notifiable): array{ return ['mail', 'database'];}- Email for external delivery
- Database for in-app notification bell
Pass Models as Constructor Properties
Section titled “Pass Models as Constructor Properties”Use constructor property promotion:
public function __construct( public Booking $booking, public Offer $offer) {}Models are serialized for queue, relationships preserved.
Format Email Content
Section titled “Format Email Content”Use MailMessage fluent interface:
return (new MailMessage()) ->subject('Clear, specific subject') ->greeting('Hello ' . $notifiable->name . '!') ->line('First line of content') ->line('**Bold:** for emphasis') ->action('Action Button Text', $url) ->line('Closing line');Return Structured Database Data
Section titled “Return Structured Database Data”Provide specific fields for Filament notification panel:
public function toArray(object $notifiable): array{ return [ 'title' => 'Short Title', // Required 'message' => 'Brief message', // Required 'record_id' => $this->model->id, // Optional 'type' => 'booking', // Optional // Additional context fields... ];}Test Comprehensively
Section titled “Test Comprehensively”Test notifications with:
- Recipient selection logic
- Channel verification (mail + database)
- Data payload validation
- Multiple recipient scenarios
Use Notification::fake() to avoid actual sending.
Recipient Patterns
Section titled “Recipient Patterns”Single User
Section titled “Single User”$user->notify(new MyNotification($model));Multiple Users (Collection)
Section titled “Multiple Users (Collection)”Notification::send($users, new MyNotification($model));Query-Based Recipients
Section titled “Query-Based Recipients”$admins = User::role(Role::Admin->value)->get();Notification::send($admins, new MyNotification($model));Merge and Deduplicate
Section titled “Merge and Deduplicate”$admins = User::role(Role::Admin->value)->get();$suppliers = User::where('supplier_id', $supplierId)->get();$recipients = $admins->merge($suppliers)->unique('id');
Notification::send($recipients, new MyNotification($model));Local Testing
Section titled “Local Testing”Use Mailpit
Section titled “Use Mailpit”Web UI: http://localhost:8025
View all sent emails without actual delivery.
See: Mailpit Setup
Test Command
Section titled “Test Command”# Send test notification./vendor/bin/sail artisan notification:test user@example.comTroubleshooting
Section titled “Troubleshooting”Notifications not sending:
- Queue worker running?
sail artisan queue:work - Check logs:
storage/logs/laravel.log - Verify MAIL_* env vars
Email not received:
- Check Mailpit UI (http://localhost:8025)
- Verify
via()includes ‘mail’ - Check queue failed jobs table
Database notifications missing:
- Verify
via()includes ‘database’ - Check
notificationstable directly - User must be
Notifiable(default on User model)
Related
Section titled “Related”- Notification System
- Queue System
- Mailpit Setup
- Laravel Docs: Notifications