詹姆斯·米尔斯 / laravel-notification-rate-limit
速率限制器,以避免用户收到重复的通知。
Requires
- php: ^8.2
- illuminate/support: ^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0
- timacdonald/log-fake: ^2.2.0
This package is auto-updated.
Last update: 2024-08-25 21:53:58 UTC
README
在Laravel中使用Laravel原生速率限制器限制通知的速率,以避免用户收到重复的通知。
版本兼容性
安装
您可以通过composer安装此包
composer require jamesmills/laravel-notification-rate-limit
更新通知
实现ShouldRateLimit
接口,并将RateLimitedNotification
特质添加到您希望进行速率限制的通知中。
<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use Jamesmills\LaravelNotificationRateLimit\RateLimitedNotification; use Jamesmills\LaravelNotificationRateLimit\ShouldRateLimit; class NotifyUserOfOrderUpdateNotification extends Notification implements ShouldRateLimit { use Queueable; use RateLimitedNotification; ...
发布配置
本包中的所有内容都有一些有见地的全局默认值。然而,您可以覆盖配置中的所有内容,并且许多选项也可以根据每个通知进行进一步定制(见下文)。
使用以下命令发布。
php artisan vendor:publish --provider="Jamesmills\LaravelNotificationRateLimit\LaravelNotificationRateLimitServiceProvider"
从2.x版本升级
如果您正在从版本2升级,请注意,NotificationRateLimitReached
事件签名已更改,并包含有关跳过的通知的更多信息。如果您已实现该事件类的自己的版本,您需要更新构造函数签名以接受这些额外的参数。升级过程中不需要进行其他更改。
重要注意事项
队列和延迟通知
只有当通知实际正在派送时才会检查速率限制。
如果通知被发送到队列,或者通知带有延迟(例如 $user->notify($notification->delay(...))
),则速率限制将只在通知即将派送到用户时才考虑。
使用多个类型的可通知模型时的标识符冲突
如果您有多个使用可通知特质的模型(例如,多种类型的用户模型),您应将可通知实例的类名添加到缓存键中(见下文自定义可通知标识符)。
选项
事件
默认情况下,当通知被跳过时,将触发NotificationRateLimitReached
事件。您可以使用配置中的event
选项来自定义此行为。
覆盖通知的速率限制时间
默认情况下,速率限制的通知将被速率限制60
秒。
使用rate_limit_seconds
配置设置全局更新。
通过将以下内容添加到通知中按单个通知进行更新
// Change rate limit to 1 hour protected $rateLimitForSeconds = 3600;
记录跳过的通知
默认情况下,此包将记录所有跳过的通知。
使用log_skipped_notifications
配置设置全局更新。
通过将以下内容添加到通知中按单个通知进行更新
// Do not log skipped notifications protected $logSkippedNotifications = false;
跳过唯一通知
默认情况下,速率限制器使用由一些有见地的默认值组成的缓存键。其中一个默认键是serialize($notification)
。您可能希望将其关闭。
使用should_rate_limit_unique_notifications
配置设置全局更新。
通过将以下内容添加到通知中按单个通知进行更新
protected $shouldRateLimitUniqueNotifications = false;
自定义缓存键
您可能想要自定义用于缓存键的部分。您可以通过向通知中添加如下代码来完成此操作
public function rateLimitCustomCacheKeyParts() { return [ $this->account_id ]; }
自定义可通知标识符
默认情况下,我们使用Notifiable
实例的主键或$id
字段来识别通知的接收者。
如果出于某种原因您不想使用$id
,您可以为您的Notifiable
模型添加一个rateLimitNotifiableKey()
方法,并返回一个包含要使用的关键字的字符串。
例如,如果有多个用户可以属于一个组,而你只想让组中的一个人(任何一个人)接收通知,你可能需要返回组ID而不是用户ID
class User extends Authenticatable { use Notifiable; protected $fillable = ['id', 'name', 'email', 'groupId']; public function rateLimitNotifiableKey(): string { return $this->group_id; } }
同样,如果你在应用程序中有多个模型实现了Notifiable
接口,仅使用id
可能会导致冲突(例如,Agent
#41 接收通知,从而阻止 Customer
#41 接收类似的通知)。在这种情况下,你可能需要在每个模型的键中返回一个包含类名的标识符
class Customer extends Authenticatable { use Notifiable; protected $fillable = ['id', 'name', 'email']; public function rateLimitNotifiableKey(): string { return get_class($this) . '#' . $this->id; } } class Agent extends Authenticatable { use Notifiable; protected $fillable = ['id', 'name', 'email']; public function rateLimitNotifiableKey(): string { return get_class($this) . '#' . $this->id; } }
高级用法
因应用程序定义的原因丢弃通知
可能存在这样的情况,你希望实现自定义应用程序逻辑来决定即使速率限制器本身不会阻止发送通知,也应该丢弃通知(例如,跟踪并设置特定用户可以接收特定通知的总次数上限)。
为此,向你的通知中添加一个rateLimitCheckDiscard
函数,并返回一个非空字符串来指示丢弃通知的原因。示例
public function rateLimitCheckDiscard(string $key): ?string { $max_send_key = $key . '_send_count'; $count = Cache::get($max_send_key, 0); if ($count >= 3) { return 'Max send limit reached'; } Cache::put($max_send_key, $count + 1); return null; }
注意
- 字符串 'Rate limit reached'(在
NotificationRateLimitReached::REASON_LIMITER
中定义)被保留,以指示速率限制器阻止通知分发。 - 如果速率限制器本身阻止通知分发,则不会调用自定义的
rateLimitCheckDiscard
。 - 如果
rateLimitCheckDiscard
返回一个非空字符串,则- 通知将不会分发并会被丢弃;并且
- 尝试将不会作为对速率限制器本身的'击中'计数。
rateLimitCheckDiscad
返回的'原因'将被包括在日志条目中(如果已配置),并转发给NotificationRateLimitReached
事件。
延迟(而不是丢弃)通知
如果你希望延迟/推迟通知的发送而不是完全丢弃它(见问题 #33),一个实现此功能的示例可以在https://github.com/tibbsa/lnrl_deferral_example/找到。
测试
composer test
变更日志
请参阅CHANGELOG以获取有关最近更改的更多信息。
贡献
请参阅CONTRIBUTING以获取详细信息。
安全
如果你发现任何安全相关的问题,请通过电子邮件anthony@trinimex.ca和james@jamesmills.co.uk联系,而不是使用问题跟踪器。
鸣谢
许可协议(Treeware)
此软件包100%免费且开源,遵循MIT许可协议(MIT)。你可以随意使用。
此软件包是Treeware。如果你在生产中使用它,那么我们请求你为世界买一棵树以感谢我们的工作。通过为Treeware森林做出贡献,你将创造就业机会并恢复野生动物栖息地。
灵感
本包的灵感来源于Scott Wakefield撰写的文章《Laravel中的速率限制通知》(原文链接:[https://twitter.com/scottpwakefield](https://twitter.com/scottpwakefield) ,现可通过[Internet Archive的Wayback Machine](https://web.archive.org/web/20210303043709/https://scottwakefield.co.uk/journal/rate-limiting-notifications-in-laravel/)访问)。