ronasit / laravel-exponent-push-notifications
Exponent push notifications driver for laravel
Package info
github.com/RonasIT/laravel-exponent-push-notifications
pkg:composer/ronasit/laravel-exponent-push-notifications
Requires
- php: ^8.3
- alymosul/exponent-server-sdk-php: 1.3.*
- laravel/framework: >=11
Requires (Dev)
- laravel/pint: ^1.27
- mockery/mockery: ^1.6.12
- orchestra/testbench: >=9.5.1
- phpunit/phpunit: >=11.5.5
- ronasit/laravel-helpers: ^3.5.8
This package is auto-updated.
Last update: 2026-06-02 03:32:33 UTC
README
This package provides an Expo push notification channel for Laravel, allowing you to send notifications to mobile devices via the Expo SDK.
Contents
Installation
Install the package via composer:
composer require ronasit/laravel-exponent-push-notifications
Publish the config file (optionally):
php artisan vendor:publish --provider="NotificationChannels\ExpoPushNotifications\ExpoPushNotificationsServiceProvider" --tag="config"
Storage Drivers
Package provides several drivers to store the push tokens:
| Driver | When to use |
|---|---|
file (default) |
Simple setups, single-server, no database required |
database |
Multi-server deployments, persistent storage, flexible queries |
Storage driver may be configured via the EXPONENT_PUSH_NOTIFICATION_INTERESTS_STORAGE_DRIVER env variable.
Database driver
To use the database driver need to publish and run package migration:
php artisan vendor:publish --provider="NotificationChannels\ExpoPushNotifications\ExpoPushNotificationsServiceProvider" --tag="migrations" php artisan migrate
Important
The migration uses the table name defined in interests.database.table_name from the config (exponent_push_notification_interests by default).
Usage
To send an Expo push notification, add ExpoChannel::class to the via() method of your notification class and implement the toExpoPush() method:
use App\Models\User; use NotificationChannels\ExpoPushNotifications\ExpoChannel; use NotificationChannels\ExpoPushNotifications\ExpoMessage; use Illuminate\Notifications\Notification; class AccountApproved extends Notification { public function via(User $notifiable): array { return [ExpoChannel::class]; } public function toExpoPush(User $notifiable): ExpoMessage { return ExpoMessage::create() ->badge(1) ->enableSound() ->title("Congratulations!") ->body("Your {$notifiable->service} account was approved!"); } }
Push tokens API
The package automatically registers the following endpoints for managing device subscriptions:
POST /exponent/devices/subscribe
| Field | Type | Required | Description |
|---|---|---|---|
expo_token |
string | Yes | The Expo push token of the device to subscribe |
POST /exponent/devices/unsubscribe
| Field | Type | Required | Description |
|---|---|---|---|
expo_token |
string | No | The Expo push token to remove. If omitted, all tokens for the authenticated user will be removed |
The middleware applied to these endpoints is configured via the middleware key in the config file.
The package registers all endpoints automatically. To customize their middleware, prefix, or guards, call Route::expo() in your routes file — this disables the automatic registration:
Route::prefix('v{version}')->group(function () { Route::middleware('auth_group')->group(function () { // other routes Route::expo(); }); });
Message customization
ExpoMessage may be customized using the following methods:
| Method | Description | Notes |
|---|---|---|
title |
Sets the notification title | Default: null |
body |
Sets the notification body | Default: '' |
enableSound |
Enables the notification sound | Sets sound to 'default' |
disableSound |
Mutes the notification sound | Sets sound to null |
badge |
Sets the badge count on the app icon | Default: 0 |
setTtl |
Sets the time to live in seconds | Default: 0 |
setJsonData |
Sets additional payload data | Accepts array or JSON string. Throws CouldNotCreateMessage on invalid JSON |
setChannelId |
Sets the notification channel ID | Android only |
priority |
Sets the delivery priority | Default: PriorityEnum::Default.Available: ::Default, ::Normal, ::High |
setInterruptionLevel |
Sets the interruption level | iOS only. Available: InterruptionLevelEnum::Active, ::Critical, ::Passive, ::TimeSensitive |
For example, to send a high-priority time-sensitive notification on iOS:
use NotificationChannels\ExpoPushNotifications\ExpoMessage; use NotificationChannels\ExpoPushNotifications\Enums\PriorityEnum; use NotificationChannels\ExpoPushNotifications\Enums\InterruptionLevelEnum; ExpoMessage::create() ->title('Important!') ->body('This is a critical alert.') ->priority(PriorityEnum::High) ->setInterruptionLevel(InterruptionLevelEnum::TimeSensitive);
Routing a message
An interest is a named subscription that links a device's push token to a logical target (e.g. a specific user). When sending a notification, the package looks up all tokens registered under that interest and delivers the message to them.
By default, the interest that a message is sent to is derived from the notifiable model using the {ClassName}.{id} convention (e.g. App.Models.User.1).
You can override this by adding a routeNotificationForExpoPushNotifications() method to your notifiable model:
use Illuminate\Notifications\Notifiable; class User extends Model { use Notifiable; public function routeNotificationForExpoPushNotifications(): string { return 'App.Models.User.' . $this->id; } }
Changelog
Please see CHANGELOG for more information on what has changed recently.
Testing
composer test
Security
If you discover any security related issues, please use the GitHub issue tracker.
Contributing
Please see CONTRIBUTING for details.
Credits
- Aly Suleiman — original author
- RonasIT
- All Contributors
License
The MIT License (MIT). Please see License File for more information.