Implementing Interactive Database Notifications with Laravel and Livewire
Overview
In a modern SaaS application, real-time feedback is non-negotiable. This tutorial breaks down how to implement a database-driven notification "bell" using
Prerequisites
To follow this guide, you should have a baseline understanding of the PHP language and the
Key Libraries & Tools
- Laravel: The core PHP framework providing the notification engine.
- Livewire: A full-stack framework for Laravel that builds dynamic interfaces without leaving PHP.
- Laravel Migrations: Used to generate the system-standard
notificationstable.
Code Walkthrough
1. Database Setup
First, you must create the storage for your notifications. Run the following command to generate the migration:
php artisan notifications:table
php artisan migrate
2. The Notification Class
Create a notification class that accepts your model (e.g., a Task) and defines the database channel.
public function via($notifiable)
{
return ['database'];
}
public function toArray($notifiable)
{
return [
'task_id' => $this->task->id,
'message' => 'A new task was assigned to you.'
];
}
3. The Livewire Component
The wire:poll to keep the data fresh.
// Blade Template Snippet
<div wire:poll.30s>
<button>
Notifications ({{ $unreadCount }})
</button>
@if($unreadCount > 0)
<button wire:click="markAllAsRead">Mark all as read</button>
@endif
</div>
Syntax Notes
via method to determine delivery channels (mail, database, slack). Inside the wire:poll.30s directive is a declarative way to trigger a re-render every 30 seconds, ensuring the UI stays in sync with the backend state.
Practical Examples
This pattern is standard for SaaS dashboards where users need to be alerted to specific actions, such as a team member commenting on a project or a system subscription nearing its renewal date.
Tips & Gotchas
Don't forget that the notifications table stores data as JSON. If you change your notification data structure, older records might cause errors in your Blade templates if you don't handle null checks properly. Always use wire:poll sparingly to avoid unnecessary server load.
