dive-be/laravel-expo-channel
最新稳定版本:2.0.0
Composer 安装命令:
composer require dive-be/laravel-expo-channel
包简介
Expo Notifications Channel for Laravel
README 文档
README
Important
This channel has finally moved to where it belongs (Laravel Notification Channels project), and thus this repository has been abandoned. Please use the official channel from now on.
Expo Notifications Channel
Expo channel for pushing notifications to your React Native apps.
Contents
- Disclaimer
- Installation
- Additional Security
- Usage
- Expo Message Request Format
- Testing
- Changelog
- Contributing
- Security
- Credits
- License
Disclaimer
This package is not (yet) part of the Laravel Notification Channels project, because the maintainer seems to be inactive and the existing expo channel has never been completed and is pretty much abandoned. This package respects all of the project's conventions (namespace, message creation ...), so a possible migration in the future should just be about replacing the package's name in your composer.json.
Installation
You can install the package via composer:
composer require dive-be/laravel-expo-channel
Additional Security (optional)
You can require any push notifications to be sent with an additional Access Token before Expo delivers them to your users.
If you want to make use of this additional security layer, add the following to your config/services.php file:
'expo' => [ 'access_token' => env('EXPO_ACCESS_TOKEN'), ],
Usage
You can now use the expo channel in the via() method of your Notifications.
Notification / ExpoMessage
First things first, you need to have a Notification that needs to be delivered to someone. Check out the Laravel documentation for more information on generating notifications.
final class SuspiciousActivityDetected extends Notification { public function toExpo($notifiable): ExpoMessage { return ExpoMessage::create('Suspicious Activity') ->body('Someone tried logging in to your account!') ->data($notifiable->only('email', 'id')) ->expiresAt(Carbon::now()->addHour()) ->priority('high') ->playSound(); } public function via($notifiable): array { return ['expo']; } }
Note Detailed explanation regarding the Expo Message Request Format can be found here.
You can also apply conditionals to ExpoMessage without breaking the method chain:
public function toExpo($notifiable): ExpoMessage { return ExpoMessage::create('Suspicious Activity') ->body('Someone tried logging in to your account!') ->when($notifiable->wantsSound(), fn ($msg) => $msg->playSound()) ->unless($notifiable->isVip(), fn ($msg) => $msg->normal(), fn ($msg) => $msg->high()); }
Notifiable / ExpoPushToken
Next, you will have to set a routeNotificationForExpo() method in your Notifiable model.
Unicasting (single device)
The method must return either an instance of ExpoPushToken or null. An example:
final class User extends Authenticatable { use Notifiable; protected $casts = ['expo_token' => ExpoPushToken::class]; public function routeNotificationForExpo(): ?ExpoPushToken { return $this->expo_token; } }
Warning No notifications will be sent in case of
null.
Note More info regarding the model cast can be found here.
Multicasting (multiple devices)
The method must return an array<int, ExpoPushToken> or Collection<int, ExpoPushToken>,
the specific implementation depends on your use case. An example:
final class User extends Authenticatable { use Notifiable; /** * @return Collection<int, ExpoPushToken> */ public function routeNotificationForExpo(): Collection { return $this->devices->pluck('expo_token'); } }
Warning No notifications will be sent in case of an empty
Collection.
Sending
Once everything is in place, you can simply send a notification by calling:
$user->notify(new SuspiciousActivityDetected());
Validation
You ought to have an HTTP endpoint that associates a given ExpoPushToken with an authenticated User so that you can deliver push notifications. For this reason, we're also providing a custom validation ExpoPushTokenRule class which you can use to protect your endpoints. An example:
final class StoreDeviceRequest extends FormRequest { public function rules(): array { return [ 'device_id' => ['required', 'string', 'min:2', 'max:255'], 'token' => ['required', ExpoPushToken::rule()], ]; } }
Model casting
The ExpoChannel expects you to return an instance of ExpoPushToken from your Notifiables. You can easily achieve this by applying the ExpoPushToken as a custom model cast. An example:
final class User extends Authenticatable { use Notifiable; protected $casts = ['expo_token' => AsExpoPushToken::class]; }
This custom value object guarantees the integrity of the push token. You should make sure that only valid tokens are saved.
Handling failed deliveries
Unfortunately, Laravel does not provide an OOB solution for handling failed deliveries. However, there is a NotificationFailed event which Laravel does provide so you can hook into failed delivery attempts. This is particularly useful when an old token is no longer valid and the service starts responding with DeviceNotRegistered errors.
You can register an event listener that listens to this event and handles the appropriate errors. An example:
final readonly class HandleFailedExpoNotifications { public function handle(NotificationFailed $event) { if ($event->channel !== 'expo') return; /** @var ExpoError $error */ $error = $event->data; // Remove old token if ($error->type->isDeviceNotRegistered()) { $event->notifiable->update(['expo_token' => null]); } else { // do something else like logging... } } }
The NotificationFailed::$data property will contain an instance of ExpoError which has the following properties:
final readonly class ExpoError { private function __construct( public ExpoErrorType $type, public ExpoPushToken $token, public string $message, ) {} }
Expo Message Request Format
The ExpoMessage class contains the following methods for defining the message payload. All of these methods correspond to the available payload defined in the Expo Push documentation.
- Badge (iOS)
- Body
- Category ID
- Channel ID (Android)
- JSON data
- Expiration
- Mutable content (iOS)
- Notification sound (iOS)
- Priority
- Subtitle (iOS)
- Title
- TTL (Time to live)
Badge (iOS)
Sets the number to display in the badge on the app icon.
badge(int $value)
Note The value must be greater than or equal to 0.
Body
Sets the message body to display in the notification.
body(string $value) text(string $value)
Note The value must not be empty.
Category ID
Sets the ID of the notification category that this notification is associated with.
categoryId(string $value)
Note The value must not be empty.
Channel ID (Android)
Sets the ID of the Notification Channel through which to display this notification.
channelId(string $value)
Note The value must not be empty.
JSON data
Sets the JSON data for the message.
data(Arrayable|Jsonable|JsonSerializable|array $value)
Warning We're compressing JSON payloads that exceed 1 KiB using Gzip (if
ext-zlibis available). While you could technically send more than 4 KiB of data, this is not recommended.
Expiration
Sets the expiration time of the message. Same effect as TTL.
expiresAt(DateTimeInterface|int $value)
Warning
TTLtakes precedence if both are set.
Note The value must be in the future.
Mutable content (iOS)
Sets whether the notification can be intercepted by the client app.
mutableContent(bool $value = true)
Notification sound (iOS)
Play the default notification sound when the recipient receives the notification.
playSound()
Warning Custom sounds are not supported.
Priority
Sets the delivery priority of the message.
priority(string $value)
default()
normal()
high()
Note The value must be
default,normalorhigh.
Subtitle (iOS)
Sets the subtitle to display in the notification below the title.
subtitle(string $value)
Note The value must not be empty.
Title
Set the title to display in the notification.
title(string $value)
Note The value must not be empty.
TTL (Time to live)
Set the number of seconds for which the message may be kept around for redelivery.
ttl(int $value) expiresIn(int $value)
Warning Takes precedence over
expirationif both are set.
Note The value must be greater than 0.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email oss@dive.be instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
dive-be/laravel-expo-channel 适用场景与选型建议
dive-be/laravel-expo-channel 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 81 次下载、GitHub Stars 达 8, 最近一次更新时间为 2022 年 08 月 31 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「notifications」 「laravel」 「expo」 「exponent」 「react-native」 「dive」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 dive-be/laravel-expo-channel 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 dive-be/laravel-expo-channel 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 dive-be/laravel-expo-channel 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A Laravel Nova package that adds a notification feed in your Nova app.
Expo Push Notifications Driver for Laravel Notifications, PHP 7.4
Yii2 extension for working with Expo push notifications
Send push notifications with Expo
Captures outgoing SMS notifications
Server-side library for working with Expo using PHP
统计信息
- 总下载量: 81
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 8
- 点击次数: 13
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2022-08-31
