via()返回值必须严格匹配已注册渠道名,否则laravel静默忽略通知;notifications表需添加notifiable_id+notifiable_type联合索引以提升查询性能。

通知发不出去,八成是 via() 写错了,不是配置问题,也不是队列没跑,而是 Laravel 直接跳过发送——连日志都不打。
via() 返回值必须严格匹配已注册渠道名
这个方法是通知的“开关”,不是装饰。返回空数组、拼错名字(比如 'mails')、或写了没装包的渠道(比如 'vonage' 但没 composer require vonage/laravel),Laravel 就静默忽略整条通知。
-
return ['mail']→ 需已配MAIL_MAILER,且toMail()方法存在 -
return ['database']→ 需先执行php artisan notifications:table && php artisan migrate -
return ['mail', 'database']→ 两个方法都得实现:toMail()和toDatabase() -
return ['broadcast']→ 类必须实现ShouldBroadcast,且toBroadcast()存在
数据库通知查得慢?缺索引是硬伤
用户通知量一过几千,$user->unreadNotifications 就卡顿,根本不是 PHP 或 Redis 的问题,是 notifications 表没建联合索引。
- 必须加
notifiable_id + notifiable_type联合索引,这是按用户查通知的命脉 - 如果还常做“未读筛选”,再加
notifiable_id + notifiable_type + read_at复合索引 -
data字段是 JSON 序列化存的,别指望用whereJsonContains()查内容——它不走索引,查得越深越慢
广播通知收不到?前端订阅和后端频道类型必须咬死
广播失败极少是驱动没配对,更多是频道类型、鉴权路径、前端订阅三者没对齐。
- 私有频道(
private-user.123)必须走鉴权:前端订阅时触发/api/broadcasting/auth,后端得返回 200 + auth token - 频道名要完全一致:通知类里
toBroadcast()返回的onConnection('redis')和前端channel('private-user.123')必须字面匹配 - 别漏掉
App\Providers\BroadcastServiceProvider里的Broadcast::routes(),否则鉴权路由压根不存在
标记已读别先 find() 再 markAsRead()
常见写法 $notification = $user->notifications()->find($id); $notification->markAsRead(); 看似自然,实则多一次查询。
- 直接用
$user->notifications()->where('id', $id)->markAsRead(),一行搞定,省 DB 查询 - 批量标记也一样:
$user->notifications()->whereIn('id', $ids)->markAsRead() - 如果只是想取未读数,
$user->unreadNotifications->count()比$user->notifications()->whereNull('read_at')->count()更快——前者走缓存关系,后者走 SQL
最易被忽略的是 via() 的返回值校验和 notifications 表索引补全。这两个点不处理,其他所有配置都白搭。











