Laravel如何实现实时消息推送?(Pusher/Soketi方案)

1次阅读

laravel广播系统生效需三处配置对齐:broadcast_driver=pusher、config/broadcasting.php中pusher连接配置、config/services.php中pusher数组;pusher_app_cluster须填对(如mt1);broadcastserviceprovider须启用;每次改.env后需执行php artisan config:clear;私有频道鉴权接口必须返回含auth字段的json;前端js变量需以mix_开头并经laravel mix注入;soketi替代pusher时需显式禁用tls并匹配协议。

Laravel如何实现实时消息推送?(Pusher/Soketi方案)

Pusher 配置必须三处对齐,缺一不可

不是填了 .env 就算完事。Laravel 广播系统真正生效,要同时满足三个地方完全一致:BROADCAST_DRIVER=pusher(开关)、config/broadcasting.phpconnections.pusher 的配置字段、以及 config/services.php 中的 pusher 数组(Laravel 10+ 后者仅作备用,但若你手动改过前者,就容易漏掉它)。

  • PUSHER_APP_CLUSTER 必须填对——2026 年新创建的 Pusher 应用默认是 mt1,填成 us2eu 会导致连接静默失败,控制台无报错,前端收不到任何事件
  • BroadcastServiceProvider 必须在 config/app.phpproviders 数组中取消注释,否则 /api/broadcasting/auth 根本不存在,私有频道鉴权直接 404
  • 别信“自动加载”,每次改完 .env 都要跑 php artisan config:clear,否则缓存会掩盖配置错误

私有频道监听失败?大概率是 authEndpoint 返回 403 或格式不对

前端用 echo.private('xxx') 时,Laravel 默认发 POST 到 /api/broadcasting/auth 请求鉴权。这个接口返回的不是 http 状态码决定成败,而是响应体 json 是否含 auth 字段且签名有效。

  • 常见错误:控制器里写了 return response()->json(['Error' => 'unauthorized']); —— 这会返回 200 + 错误 JSON,Pusher SDK 认为鉴权成功,但实际没给 auth,前端就卡在 “connecting” 状态
  • 正确返回必须是:{"auth":"xxxxx:yyyyy"},且 header 为 Content-Type: application/json
  • 频道名大小写敏感、前后空格、字符串 vs 整数拼接(比如 'private-chat.' . $id$id 是 int 123 和 String “123”,生成的频道名不同)都会导致后端授权通过、前端订阅失败

前端 JS 读不到环境变量?检查 MIX_ 前缀和 Laravel Mix 编译

process.env.MIX_PUSHER_APP_KEY 不是凭空出现的。Laravel Mix 只会把 .env 中以 MIX_ 开头的变量注入到前端运行时环境,原始的 PUSHER_APP_KEY 对 JS 完全不可见。

  • 如果 JS 控制台报 Invalid key 或连接被拒绝,先 console.log(process.env) 看是否为空——90% 是忘了加 MIX_ 前缀
  • mix.webpackConfig 中若自定义了 define,可能覆盖默认行为,建议优先用标准方式:在 .envMIX_PUSHER_APP_KEY=xxx,然后 npm run dev 重新编译
  • 别在 bootstrap.js 里硬编码 key,既不安全也不便于多环境切换

Soketi 替代 Pusher?关键在广播驱动和 websocket 兼容性

Soketi 是开源 Pusher 协议兼容服务器,优势是自托管、无调用费用,但不是“装上就能换”。它只替代 Pusher 的服务端角色,Laravel 侧仍需走 pusher 驱动,且必须严格匹配协议版本。

  • Soketi v2.x 默认启用 ws://,而 Laravel Echo 默认走 wss://;若未配 https 或 Soketi 未开启 TLS,前端会报 WebSocket connection to 'ws://...' failed
  • 需要在 config/broadcasting.phppusher 配置中显式设置 'useTLS' => false,并确保 'host''port' 指向 Soketi 实例(如 'host' => 'localhost', 'port' => 6001
  • 别忽略 Soketi 的 CORS 和 origin 白名单配置,否则 auth 请求会被浏览器拦截,现象是 Network 面板里 /broadcasting/auth 显示 (canceled)

真实项目里最耗时间的从来不是写代码,而是频道名拼错、环境变量漏前缀、集群填错这三件事反复交叉验证。只要频道名、auth 响应、JS 变量三者严丝合缝,剩下的就是照着文档抄几行。

text=ZqhQzanResources