laravel-notification-system maintained by abdogoda
Laravel Notification System
A production-ready, highly extensible, multi-channel notification framework for Laravel applications developed by Abdulrhman Goda. Designed for single and multi-authentication, unlimited guards, customizable recipients, delivery tracking, localization, queued channels, and built-in Blade/Tailwind admin dashboard components.
Requirements
- PHP 8.2+
- Laravel 10, 11, 12, or 13
Features
- Multi-Channel Architecture: Native support for
Database,Mail,FCM Push Notifications,WhatsApp (BULQ API), and extensible custom channels. - Fluent Notification Builder: Clean API (
NotificationSystem::make()->title(...)->to(...)->send()). - Dynamic Recipient Resolution: Pass Eloquent models, collections, query builders, arrays, or guard names.
- Immutable DTO Layer: Strong type safety with
NotificationData,RecipientData,ChannelData,AttachmentData, andMailData. - Delivery Logging: Detailed logging table (
notification_logs) tracking status, attempts, response payload, exception trace, and duration. - Event-Driven Lifecycle: Event hooks (
NotificationCreating,NotificationSending,NotificationSent,NotificationFailed,ChannelSending,ChannelSent,ChannelFailed). - Queued & Async Delivery: Asynchronous queued delivery with configurable backoff, retry, and per-channel queue names.
- Recipient Localization: Automatic locale detection from recipient preferences with fallback.
- Admin Panel & Blade Components: Ready-to-use Blade components (
<x-notification-card>,<x-notification-table>,<x-notification-form>,<x-recipient-selector>,<x-channel-selector>,<x-statistics-widget>). - REST API Endpoints: Production API controllers for mobile and SPA clients.
Installation
1. Require via Composer
composer require abdogoda/laravel-notification-system
2. Publish Configuration & Migrations
# Publish everything
php artisan vendor:publish --provider="NotificationSystem\NotificationSystemServiceProvider"
# Or publish individually
php artisan vendor:publish --tag=notification-system-config
php artisan vendor:publish --tag=notification-system-migrations
php artisan vendor:publish --tag=notification-system-views
php artisan vendor:publish --tag=notification-system-translations
php artisan vendor:publish --tag=notification-system-assets
3. Run Migrations
php artisan migrate
Quick Start
Basic Fluent Builder
use NotificationSystem\Facades\NotificationSystem;
NotificationSystem::make()
->title('Welcome to the Platform!')
->body('Thank you for joining our academy.')
->channels(['database', 'mail', 'fcm'])
->to($user)
->locale('ar')
->data([
'action_url' => '/dashboard',
'type' => 'welcome_onboarding'
])
->send();
Sending to Multiple Guards / Audiences
NotificationSystem::make()
->title('Scheduled Maintenance Alert')
->body('The system will undergo scheduled maintenance tonight at 12:00 AM.')
->channels(['database', 'fcm'])
->to(['students', 'teachers', 'merchants'])
->send();
Synchronous Delivery (Skip Queue)
NotificationSystem::make()
->title('Urgent Alert')
->body('Action required immediately.')
->to($user)
->sendNow();
Queued with Delay
NotificationSystem::make()
->title('Reminder')
->body('Your appointment is in 1 hour.')
->to($user)
->queue(true, delaySeconds: 3600)
->send();
Email with Attachments
NotificationSystem::make()
->title('Invoice Ready')
->body('Your invoice is attached.')
->email(send: true, greeting: 'Dear Customer')
->attach('/path/to/invoice.pdf', name: 'Invoice.pdf', mime: 'application/pdf')
->to($user)
->send();
Configuration Reference
After publishing, the config file is at config/notification-system.php:
Default Channels
'default_channels' => ['database'],
Locale
'default_locale' => 'ar',
'locale_column' => 'lang', // Model attribute for preferred locale
Queue Settings
'queue' => [
'enabled' => true,
'connection' => env('NOTIFICATION_QUEUE_CONNECTION', 'default'),
'queue_name' => env('NOTIFICATION_QUEUE_NAME', 'notifications'),
'backoff' => [5, 15, 60], // Retry backoff in seconds
'max_tries' => 3,
'channel_queues' => [ // Per-channel queue names
'mail' => 'emails',
'fcm' => 'push-notifications',
'whatsapp' => 'whatsapp',
],
],
Guards Setup
Map guard names to Eloquent models. These are resolved when you pass guard strings to ->to():
'guards' => [
'admin' => [
'model' => \App\Models\Admin::class,
'label' => 'Admins',
],
'student' => [
'model' => \App\Models\Student::class,
'label' => 'Students',
],
],
Channel Credentials
'channels' => [
'whatsapp' => [
'api_url' => env('BULQ_WHATSAPP_API_URL'),
'token' => env('BULQ_WHATSAPP_TOKEN'),
'template_name' => env('BULQ_WHATSAPP_TEMPLATE', 'login_otp'),
],
'fcm' => [
'driver_class' => env('NOTIFICATION_FCM_DRIVER', null),
],
'mail' => [
'from_address' => env('MAIL_FROM_ADDRESS', 'noreply@example.com'),
'from_name' => env('MAIL_FROM_NAME', 'Laravel'),
],
],
Delivery Logging
'table_name' => 'notification_logs',
'logging_enabled' => true,
'log_retention_days' => 90, // Set to null to keep forever
Custom Channels
You can register custom channels that implement ChannelInterface:
use NotificationSystem\Contracts\ChannelInterface;
use NotificationSystem\DTOs\NotificationData;
use NotificationSystem\DTOs\RecipientData;
class SlackChannel implements ChannelInterface
{
public function send(RecipientData $recipient, NotificationData $notification): array|bool
{
// Your Slack sending logic here
return ['status' => 'sent'];
}
}
Register it in a service provider:
use NotificationSystem\Facades\NotificationSystem;
NotificationSystem::extend('slack', SlackChannel::class);
Then use it:
NotificationSystem::make()
->title('Hello Slack!')
->channels(['database', 'slack'])
->to($user)
->send();
FCM Setup
To use FCM push notifications, implement FcmDriverInterface and configure it:
use NotificationSystem\Contracts\FcmDriverInterface;
class MyFcmDriver implements FcmDriverInterface
{
public function sendNotification(string $token, string $title, string $body, array $data = []): void
{
// Your Firebase sending logic
}
}
Register in a service provider:
$this->app->bind(FcmDriverInterface::class, MyFcmDriver::class);
Or set via config/env:
NOTIFICATION_FCM_DRIVER=App\Services\MyFcmDriver
Events
The package dispatches events throughout the notification lifecycle. Listen to them in your EventServiceProvider:
| Event | Fired When |
|---|---|
NotificationCreating |
Before recipients are resolved |
NotificationSending |
Before delivery starts for a recipient |
NotificationSent |
After all channels deliver for a recipient |
NotificationFailed |
If the entire delivery process throws |
ChannelSending |
Before a specific channel sends |
ChannelSent |
After a specific channel succeeds |
ChannelFailed |
After a specific channel fails |
Example Listener
use NotificationSystem\Events\NotificationSent;
class LogNotificationDelivery
{
public function handle(NotificationSent $event): void
{
logger()->info('Notification delivered', [
'notification_id' => $event->notification->id,
'recipient_id' => $event->recipient->id,
'channels' => array_keys($event->channelResults),
]);
}
}
REST API Endpoints
All routes are configurable via notification-system.routes.api:
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/notifications |
List paginated notifications |
GET |
/api/v1/notifications/unread-count |
Get unread count |
POST |
/api/v1/notifications/mark-all-read |
Mark all as read |
POST |
/api/v1/notifications/{id}/mark-read |
Mark one as read |
DELETE |
/api/v1/notifications/{id} |
Delete a notification |
DELETE |
/api/v1/notifications |
Clear all notifications |
Blade Components
Available components (all prefixed with notification-system):
<x-notification-system-notification-card :notification="$notification" :is-unread="true" />
<x-notification-system-notification-table :notifications="$notifications" />
<x-notification-system-notification-form />
<x-notification-system-recipient-selector :guards="$guardModels" />
<x-notification-system-channel-selector :selected-channels="['database', 'mail']" />
<x-notification-system-statistics-widget :total="100" :unread="5" :delivered="90" :failed="5" />
Delivery Logging
Every send attempt is logged to the notification_logs table with:
notification_id— Links to the notificationchannel— Which channel was usedstatus—pending,sending,delivered, orfailedduration_ms— How long the channel tookresponse— JSON response from the channelexception— Error message if failed
Query Log Scopes
use NotificationSystem\Models\NotificationLog;
NotificationLog::delivered()->count();
NotificationLog::failed()->forChannel('mail')->get();
NotificationLog::forRecipient('App\Models\User', 1)->recent(30)->get();
NotificationLog::olderThan(90)->delete(); // Prune old logs
Testing
composer test
Or:
vendor/bin/phpunit
The test suite uses SQLite in-memory via Orchestra Testbench.
Credits & Author
Developed with ❤️ by Abdulrhman Goda.
- Website: https://abdogoda.github.io/AG/
Contributing
Please see CONTRIBUTING.md for details.
Security
If you discover a security vulnerability, please see SECURITY.md.
License
The MIT License (MIT). Copyright © 2026 Abdulrhman Goda. Please see License File for more information.