A notification system is an important feature in almost every modern web application — from new order alerts and email verification to account activity warnings. Laravel has a very flexible built-in notification system that supports various channels such as email, database, SMS, and Slack. In this tutorial, we will focus on the two most common channels: database and email.
Preparation: The Database Notifications Table
For the database notification channel, Laravel needs a dedicated table. Create it with the command:
php artisan make:notifications-table
php artisan migrate
This creates a notifications table that stores notifications in JSON format.
Creating the Notification Class
Create a notification class using Artisan:
php artisan make:notification OrderPlaced
The file will be created at app/Notifications/OrderPlaced.php. Edit that file:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class OrderPlaced extends Notification implements ShouldQueue
{
use Queueable;
public function __construct(
protected array $orderData
) {}
// Define which channels to use
public function via(object $notifiable): array
{
return ['database', 'mail'];
}
// Content for the email
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Your Order Was Placed Successfully!')
->greeting('Hello, ' . $notifiable->name . '!')
->line('Your order #' . $this->orderData['order_number'] . ' has been received successfully.')
->line('Total payment: $' . number_format($this->orderData['total'], 2))
->action('View Order', url('/orders/' . $this->orderData['order_id']))
->line('Thank you for shopping with us!');
}
// Content for the database
public function toDatabase(object $notifiable): array
{
return [
'order_id' => $this->orderData['order_id'],
'order_number' => $this->orderData['order_number'],
'total' => $this->orderData['total'],
'message' => 'Order #' . $this->orderData['order_number'] . ' was placed successfully.',
];
}
}
Sending a Notification
There are two ways to send a notification in Laravel. Make sure the User model already uses the Notifiable trait (it does by default):
// Way 1: Through the model (Notifiable trait)
$user = User::find(1);
$user->notify(new OrderPlaced([
'order_id' => 101,
'order_number' => 'ORD-2024-001',
'total' => 250.00,
]));
// Way 2: Through the Notification facade (for many users at once)
use Illuminate\Support\Facades\Notification;
$users = User::where('is_admin', true)->get();
Notification::send($users, new OrderPlaced([
'order_id' => 101,
'order_number' => 'ORD-2024-001',
'total' => 250.00,
]));
Retrieving and Displaying Database Notifications
Database notifications are stored in the table and can be accessed through the User model's relationships:
// In the controller
$user = auth()->user();
// All notifications
$notifications = $user->notifications;
// Only the unread ones
$unread = $user->unreadNotifications;
// Unread count
$count = $user->unreadNotifications()->count();
Display them in Blade:
@foreach(auth()->user()->unreadNotifications as $notification)
<div class="notif {{ $notification->read_at ? '' : 'unread' }}">
<p>{{ $notification->data['message'] }}</p>
<small>{{ $notification->created_at->diffForHumans() }}</small>
</div>
@endforeach
Marking Notifications as Read
// Mark one notification
$notification = auth()->user()->notifications()->find($id);
$notification->markAsRead();
// Mark all as read
auth()->user()->unreadNotifications->markAsRead();
Email Configuration
Set the email configuration in the .env file:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@yourapp.com"
MAIL_FROM_NAME="${APP_NAME}"
For local testing, use Mailtrap or MAIL_MAILER=log, which writes the email to Laravel's log file.
Using a Queue for Notifications
Because our notification class implements ShouldQueue, the notification is sent asynchronously via the queue. This is very important for application performance so that sending the email doesn't block the user's request. Run the queue worker:
php artisan queue:work
For development, you can use QUEUE_CONNECTION=sync in .env so notifications are sent immediately without a queue.
Conclusion
Laravel's notification system is very powerful and easy to use. With a single notification class, you can send a message to multiple channels at once. The next step could be to explore real-time notifications using the broadcast channel with Laravel Echo and Pusher, so notifications appear instantly in the browser without refreshing the page.