cofa / notification_via_firebase_and_database
This is a package for sending notificatinon via firebase and database with good code structure
Package info
github.com/Cofa12/Notification_via_firebase_and_database
pkg:composer/cofa/notification_via_firebase_and_database
Requires
- php: ^8.2
- illuminate/config: ^10.0|^11.0|^12.0
- illuminate/notifications: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- kreait/firebase-php: ^7.0|^8.0
Requires (Dev)
- laravel/framework: ^12.58
- mockery/mockery: ^1.6
- orchestra/testbench: ^10.11
- phpunit/phpunit: ^10.0|^11.0|^12.0
- vimeo/psalm: ^5.0|^6.0
Conflicts
README
A Laravel package for sending push notifications via Firebase Cloud Messaging (FCM) and storing them in the database — using Laravel's native notification pipeline with a clean, channel-based architecture.
Features
- 🔥 Firebase Channel — Send push notifications via FCM using Laravel's standard
notify()pipeline - 💾 Database Channel — Store notifications using Laravel's built-in notification system
- 🏗️ Channel-Based Architecture — Fully integrated with
via(),toFirebase(), andtoDatabase() - 📱 Platform-Specific Configs — Android and iOS payload configuration support
- 🔑 Device Token Management — Built-in
user_device_tokenstable with active/inactive tracking - ✅ Fully Tested — Test suite using Orchestra Testbench and Mockery
- 🔍 Static Analysis — Psalm integration for type safety
Requirements
| Requirement | Version |
|---|---|
| PHP | ^8.2 |
| Laravel | ^10.0 | ^11.0 | ^12.0 |
| kreait/firebase-php | ^7.0 | ^8.0 |
Installation
Install via Composer:
composer require cofa/notification_via_firebase_and_database
Register the Service Provider
Laravel 11+ — auto-discovered, no action needed.
Laravel 10 — add to config/app.php:
'providers' => [ Cofa\NotificationViaFirebaseAndDatabase\FirebaseNotificationServiceProvider::class, ],
Configuration
1. Publish the Config File
php artisan vendor:publish --tag=firebase-notification-config
This creates config/firebase-notification.php:
return [ 'firebase' => [ 'credentials' => storage_path('app/firebase/credentials.json'), ], ];
2. Add Your Firebase Credentials
- Go to Firebase Console → Project Settings → Service Accounts
- Click Generate new private key and download the JSON file
- Place it in your project (recommended:
storage/app/firebase/credentials.json) - Add the path to
.gitignore— never commit credentials to version control
storage/app/firebase/
3. Set Up the Database
php artisan firebase-notification:install php artisan migrate
This creates two tables:
notifications— Laravel's standard notifications tableuser_device_tokens— Stores FCM tokens per user and device
user_device_tokens Schema
| Column | Type | Description |
|---|---|---|
user_id |
foreignId | References users.id |
device_token |
string | Unique FCM device token |
device_type |
enum | android, ios, web |
device_name |
string (nullable) | Optional device label |
is_active |
boolean | Whether token is active |
last_used_at |
timestamp (nullable) | Last delivery timestamp |
Usage
1. Prepare Your User Model
Add the Notifiable trait and implement routeNotificationForFirebase:
use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use Notifiable; public function routeNotificationForFirebase(): array { return $this->deviceTokens() ->where('is_active', true) ->pluck('device_token') ->toArray(); } }
2. Firebase + Database Notification (Combined)
Extend FirebaseNotification to send both push and database notifications at once:
<?php namespace App\Notifications; use Cofa\NotificationViaFirebaseAndDatabase\Contracts\FirebaseNotification; use Cofa\NotificationViaFirebaseAndDatabase\Contracts\FirebasePayload; class OrderShipped extends FirebaseNotification { public function __construct(private array $orderData) { $payload = new FirebasePayload(); $payload->setData([ 'notification' => [ 'title' => 'Order Shipped', 'body' => "Your order #{$orderData['order_id']} has been shipped!", ], 'data' => [ 'order_id' => (string) $orderData['order_id'], 'type' => 'order_shipped', ], ]); $payload->setAndroidConfiguration(['priority' => 'high']); $payload->setIOSConfiguration([ 'headers' => ['apns-priority' => '10'], 'payload' => ['aps' => ['sound' => 'default', 'badge' => 1]], ]); parent::__construct($payload); } public function via($notifiable): array { return ['firebase', 'database']; } // Optional: customize what gets stored in the database public function toDatabase($notifiable): array { return [ 'order_id' => $this->orderData['order_id'], 'message' => 'Your order has been shipped', ]; } }
Send it:
$user->notify(new OrderShipped(['order_id' => 12345]));
3. Firebase-Only Notification
use Cofa\NotificationViaFirebaseAndDatabase\Contracts\FirebaseNotification; use Cofa\NotificationViaFirebaseAndDatabase\Contracts\FirebasePayload; class PromoAlert extends FirebaseNotification { public function __construct(string $message) { $payload = new FirebasePayload(); $payload->setData([ 'notification' => ['title' => 'Special Offer', 'body' => $message], ]); parent::__construct($payload); } public function via($notifiable): array { return ['firebase']; } } $user->notify(new PromoAlert('Get 50% off today only!'));
4. Database-Only Notification
use Cofa\NotificationViaFirebaseAndDatabase\Contracts\DatabaseNotification; $user->notify(new DatabaseNotification([ 'type' => 'welcome', 'message' => 'Welcome to the platform!', ]));
5. Reading Notifications
// Get all notifications $notifications = $user->notifications; // Get only unread $unread = $user->unreadNotifications; // Mark all as read $user->unreadNotifications->markAsRead();
Advanced Usage
Platform-Specific Payload Configuration
$payload = new FirebasePayload(); $payload->setData([ 'notification' => ['title' => 'Hello', 'body' => 'World'], 'data' => ['deep_link' => 'app://home'], ]); // Android $payload->setAndroidConfiguration([ 'priority' => 'high', 'notification' => ['sound' => 'default', 'color' => '#FF5722'], ]); // iOS $payload->setIOSConfiguration([ 'headers' => ['apns-priority' => '10'], 'payload' => [ 'aps' => ['sound' => 'default', 'badge' => 1], ], ]);
Error Handling
Always wrap notifications in a try/catch for production use:
try { $user->notify(new OrderShipped($orderData)); } catch (\RuntimeException $e) { Log::error('Notification failed', [ 'user_id' => $user->id, 'error' => $e->getMessage(), ]); }
Common failure reasons:
- Missing credentials — credentials file path is wrong or file doesn't exist
- Invalid FCM token — token has expired or the app was uninstalled
- Network error — FCM service unreachable
Tip: When an FCM token returns a
NOT_REGISTEREDerror from Firebase, delete it fromuser_device_tokensto keep your token table clean.
Extending the Package
You can implement the Notification interface to create fully custom channels:
use Cofa\NotificationViaFirebaseAndDatabase\Contracts\Notification; class SmsNotification implements Notification { public function __construct(private array $data) {} public function sendNotification(array $targets): void { // your SMS logic here } }
Architecture
src/
├── Channels/
│ ├── FirebaseChannel.php # Sends to FCM
│ └── DatabaseChannel.php # Stores in database
├── Contracts/
│ ├── Notification.php # Base notification interface
│ ├── Payload.php # Base payload class
│ ├── FirebasePayload.php # Firebase-specific payload
│ ├── DatabasePayload.php # Database-specific payload
│ ├── FirebaseNotification.php # Firebase notification implementation
│ └── DatabaseNotification.php # Database notification implementation
└── FirebaseNotificationServiceProvider.php
Testing
# Run the test suite composer test # Run with coverage report vendor/bin/phpunit --coverage-html coverage # Run static analysis composer psalm
Security
- ❌ Never commit your Firebase credentials JSON to version control
- ✅ Add the credentials path to
.gitignore - ✅ Use environment variables to define the credentials path
- ✅ Validate all user input before building notification payloads
- ✅ Regularly rotate Firebase service account keys
Contributing
Contributions, issues, and feature requests are welcome! Feel free to:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes (
git commit -m 'feat: add my feature') - Push to the branch (
git push origin feature/my-feature) - Open a Pull Request
Please make sure your PR includes tests and passes composer test and composer psalm.
Changelog
v2.0.0
- Refactored to use Laravel's native notification channel architecture
- Added
via(),toFirebase(),toDatabase()channel support - Improved service provider with auto-discovery for Laravel 11+
- Removed
tymon/jwt-authconflict - Added
tymon/jwt-authto dev dependencies to verify compatibility
v1.1.2
- Added conflict declaration with
tymon/jwt-auth
v1.1.1
- Added
setAndroidConfiguration()andsetIOSConfiguration()to payload
v1.1.0
- Improved payload contract structure
v1.0.x
- Initial releases
License
This package is open-source software licensed under the MIT license.
Credits
Author: Mahmoud Gamal Email: mgcofa@gmail.com GitHub: github.com/Cofa12
Support
For bugs, questions, or feature requests, please open an issue on GitHub.