All in One Firebase push notification channel for Laravel π
See the codeSend Firebase push notifications with Laravel php framework.
You can install this package via composer:
composer require "ankurk91/fcm-notification-channel"
This package relies on laravel-firebase package to interact with Firebase
services. Here is the minimal configuration you need in your .env file
# relative or full path to the Service Account JSON file
FIREBASE_CREDENTIALS=firebase-credentials.json
You will need to create a service account and place the JSON file in your project root.
Additionally, you can update your .gitignore file
/firebase-credentials*.json
You can use the FCM channel in the via() method inside your Notification class:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use NotificationChannels\FCM\FCMChannel;
use Kreait\Firebase\Messaging\CloudMessage;
class ExampleNotification extends Notification implements ShouldQueue
{
use Queueable;
public function via($notifiable): array
{
return [FCMChannel::class];
}
public function toFCM($notifiable): CloudMessage
{
return CloudMessage::new()
->withDefaultSounds()
->withNotification([
'title' => 'Order shipped',
'body' => 'Your order for laptop is shipped.',
])
->withData([
'orderId' => '#123'
]);
}
}
Prepare your Notifiable model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* Assuming that you have a database table which stores device tokens.
*/
public function deviceTokens(): HasMany
{
return $this->hasMany(DeviceToken::class);
}
public function routeNotificationForFCM($notification): string|array|null
{
return $this->deviceTokens->pluck('token')->toArray();
}
/**
* Optional method to determine which message target to use
* We will use TOKEN type when not specified
* @see \Kreait\Firebase\Messaging\MessageTarget::TYPES
*/
public function routeNotificationForFCMTargetType($notification): ?string
{
return \Kreait\Firebase\Messaging\MessageTarget::TOKEN;
}
/**
* Optional method to determine which Firebase project to use
* We will use default project when not specified
*/
public function routeNotificationForFCMProject($notification): ?string
{
return config('firebase.default');
}
}
This package is not limited to sending notification to tokens.
You can use Laravel's on-demand notifications to send push notification to a topic or condition or multiple tokens.
<?php
use Illuminate\Support\Facades\Notification;
use Kreait\Firebase\Messaging\MessageTarget;
use App\Notification\ExampleNotification;
Notification::route('FCM', 'topicA')
->route('FCMTargetType', MessageTarget::TOPIC)
->notify(new ExampleNotification());
Notification::route('FCM', "'TopicA' in topics")
->route('FCMTargetType', MessageTarget::CONDITION)
->notify(new ExampleNotification());
Notification::route('FCM', ['token_1', 'token_2'])
->route('FCMTargetType', MessageTarget::TOKEN)
->notify(new ExampleNotification());
You can consume Laravel's inbuilt notification events
<?php
namespace App\Providers;
use Illuminate\Notifications\Events;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Events\NotificationSent::class => [
//\App\Listeners\FCMNotificationSent::class,
],
Events\NotificationFailed::class => [
\App\Listeners\FCMNotificationFailed::class,
],
];
}
Here is the example of the failed event listener class
<?php
namespace App\Listeners;
use App\Models\User;
use Illuminate\Support\Arr;
use NotificationChannels\FCM\FCMChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
use Kreait\Laravel\Firebase\Facades\Firebase;
use Illuminate\Notifications\Events\NotificationFailed;
class FCMNotificationFailed implements ShouldQueue
{
public function handle(NotificationFailed $event)
{
if ($event->channel !== FCMChannel::class) {
return;
}
/** @var User $user */
$user = $event->notifiable;
$invalidTokens = $this->findInvalidTokens($user);
if (count($invalidTokens)) {
$user->deviceTokens()->whereIn('token', $invalidTokens)->delete();
}
}
protected function findInvalidTokens(User $user): array
{
$tokens = Arr::wrap($user->routeNotificationFor('FCM'));
if (! count($tokens)) {
return [];
}
$project = $user->routeNotificationFor('FCMProject');
$response = Firebase::project($project)->messaging()->validateRegistrationTokens($tokens);
return array_unique(array_merge($response['invalid'], $response['unknown']));
}
}
Read more about validating device tokens here
Then; you may want to ignore this exception in your app/Exceptions/Handler.php
protected $dontReport = [
\NotificationChannels\FCM\Exception\InvalidRecipientException::class,
];
Please see CHANGELOG for more information what has changed recently.
composer test
If you discover any security issue, please email pro.ankurk1[at]gmail[dot]com instead of using the issue tracker.
The package is based on this rejected PR
This package is licensed under MIT License.
All in One Firebase push notification channel for Laravel π
See the codeSend Firebase push notifications with Laravel php framework.
You can install this package via composer:
composer require "ankurk91/fcm-notification-channel"
This package relies on laravel-firebase package to interact with Firebase
services. Here is the minimal configuration you need in your .env file
# relative or full path to the Service Account JSON file
FIREBASE_CREDENTIALS=firebase-credentials.json
You will need to create a service account and place the JSON file in your project root.
Additionally, you can update your .gitignore file
/firebase-credentials*.json
You can use the FCM channel in the via() method inside your Notification class:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use NotificationChannels\FCM\FCMChannel;
use Kreait\Firebase\Messaging\CloudMessage;
class ExampleNotification extends Notification implements ShouldQueue
{
use Queueable;
public function via($notifiable): array
{
return [FCMChannel::class];
}
public function toFCM($notifiable): CloudMessage
{
return CloudMessage::new()
->withDefaultSounds()
->withNotification([
'title' => 'Order shipped',
'body' => 'Your order for laptop is shipped.',
])
->withData([
'orderId' => '#123'
]);
}
}
Prepare your Notifiable model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* Assuming that you have a database table which stores device tokens.
*/
public function deviceTokens(): HasMany
{
return $this->hasMany(DeviceToken::class);
}
public function routeNotificationForFCM($notification): string|array|null
{
return $this->deviceTokens->pluck('token')->toArray();
}
/**
* Optional method to determine which message target to use
* We will use TOKEN type when not specified
* @see \Kreait\Firebase\Messaging\MessageTarget::TYPES
*/
public function routeNotificationForFCMTargetType($notification): ?string
{
return \Kreait\Firebase\Messaging\MessageTarget::TOKEN;
}
/**
* Optional method to determine which Firebase project to use
* We will use default project when not specified
*/
public function routeNotificationForFCMProject($notification): ?string
{
return config('firebase.default');
}
}
This package is not limited to sending notification to tokens.
You can use Laravel's on-demand notifications to send push notification to a topic or condition or multiple tokens.
<?php
use Illuminate\Support\Facades\Notification;
use Kreait\Firebase\Messaging\MessageTarget;
use App\Notification\ExampleNotification;
Notification::route('FCM', 'topicA')
->route('FCMTargetType', MessageTarget::TOPIC)
->notify(new ExampleNotification());
Notification::route('FCM', "'TopicA' in topics")
->route('FCMTargetType', MessageTarget::CONDITION)
->notify(new ExampleNotification());
Notification::route('FCM', ['token_1', 'token_2'])
->route('FCMTargetType', MessageTarget::TOKEN)
->notify(new ExampleNotification());
You can consume Laravel's inbuilt notification events
<?php
namespace App\Providers;
use Illuminate\Notifications\Events;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Events\NotificationSent::class => [
//\App\Listeners\FCMNotificationSent::class,
],
Events\NotificationFailed::class => [
\App\Listeners\FCMNotificationFailed::class,
],
];
}
Here is the example of the failed event listener class
<?php
namespace App\Listeners;
use App\Models\User;
use Illuminate\Support\Arr;
use NotificationChannels\FCM\FCMChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
use Kreait\Laravel\Firebase\Facades\Firebase;
use Illuminate\Notifications\Events\NotificationFailed;
class FCMNotificationFailed implements ShouldQueue
{
public function handle(NotificationFailed $event)
{
if ($event->channel !== FCMChannel::class) {
return;
}
/** @var User $user */
$user = $event->notifiable;
$invalidTokens = $this->findInvalidTokens($user);
if (count($invalidTokens)) {
$user->deviceTokens()->whereIn('token', $invalidTokens)->delete();
}
}
protected function findInvalidTokens(User $user): array
{
$tokens = Arr::wrap($user->routeNotificationFor('FCM'));
if (! count($tokens)) {
return [];
}
$project = $user->routeNotificationFor('FCMProject');
$response = Firebase::project($project)->messaging()->validateRegistrationTokens($tokens);
return array_unique(array_merge($response['invalid'], $response['unknown']));
}
}
Read more about validating device tokens here
Then; you may want to ignore this exception in your app/Exceptions/Handler.php
protected $dontReport = [
\NotificationChannels\FCM\Exception\InvalidRecipientException::class,
];
Please see CHANGELOG for more information what has changed recently.
composer test
If you discover any security issue, please email pro.ankurk1[at]gmail[dot]com instead of using the issue tracker.
The package is based on this rejected PR
This package is licensed under MIT License.