Laravel:如何为所有toMail通知添加全局拦截退信用户的中间件?
统一拦截无效邮箱的邮件通知方案
下面给你三种无需逐个修改通知类的全局处理方案,按需选择:
方案1:用Notification发送事件全局拦截
Laravel自带NotificationSending事件,发送通知前会触发这个事件,我们可以在事件监听器里直接拦截无效用户:
- 生成监听器:
php artisan make:listener BlockInvalidEmailNotifications
- 编辑监听器代码(
app/Listeners/BlockInvalidEmailNotifications.php):
namespace App\Listeners; use Illuminate\Notifications\Events\NotificationSending; class BlockInvalidEmailNotifications { public function handle(NotificationSending $event) { // 检查当前用户是否在无效邮箱记录表中 $isInvalid = \App\Models\InvalidEmail::where('user_id', $event->notifiable->id)->exists(); // 是无效用户就返回false,终止发送流程 return !$isInvalid; } }
- 在
app/Providers/EventServiceProvider.php里注册事件和监听器:
protected $listen = [ \Illuminate\Notifications\Events\NotificationSending::class => [ \App\Listeners\BlockInvalidEmailNotifications::class, ], ];
这个方案不用改任何现有通知类,全局所有邮件通知都会自动检查拦截。
方案2:创建基础通知类统一处理
如果想把逻辑集中在通知层,可以写一个基础通知类,让所有业务通知继承它:
- 创建
app/Notifications/BaseNotification.php:
namespace App\Notifications; use Illuminate\Notifications\Notification; class BaseNotification extends Notification { public function via(object $notifiable): array { // 先判断用户是否无效 $isInvalid = \App\Models\InvalidEmail::where('user_id', $notifiable->id)->exists(); // 无效用户直接返回空数组,不发送任何通知 if ($isInvalid) { return []; } // 正常用户走子类的发送渠道,或者默认返回['mail'] return parent::via($notifiable); } }
- 修改你的业务通知类,继承这个基础类:
// 原来的继承是Notification,改成BaseNotification class AlertEmailChange extends BaseNotification { // 原有代码完全保留,不需要修改via方法 }
后续新建通知时只要继承BaseNotification,就自动带上无效邮箱检查逻辑。
方案3:在用户模型层拦截
如果你的User模型用了Notifiable trait,可以重写邮件路由方法,直接返回null跳过发送:
在app/Models/User.php里添加:
public function routeNotificationForMail($notification = null) { // 检查当前用户是否在无效列表 $isInvalid = \App\Models\InvalidEmail::where('user_id', $this->id)->exists(); // 无效用户返回null,Laravel会自动跳过邮件发送 return $isInvalid ? null : $this->email; }
这个方案是从用户维度拦截,只要用户被标记为无效,所有发给该用户的邮件通知都会被阻止。
内容的提问来源于stack exchange,提问作者Micah Sklut
相关产品推荐
相关产品推荐

