Laravel广播需配置BROADCAST_DRIVER为redis、pusher或兼容服务,事件类实现ShouldBroadcast接口,配合队列与WebSocket服务器(如soketi)才能实现实时推送。

直接上结论:Laravel 广播要走 WebSocket 实时推送,BROADCAST_DRIVER 不能设为 log 或 array,必须配成 redis、pusher 或兼容 Pusher 协议的自建服务(如 soketi 或 laravel-websockets),且后端事件类必须实现 ShouldBroadcast 接口——少一个环节,前端就收不到消息。
为什么 redis 驱动 + 队列是默认推荐组合
Redis 不是 WebSocket 服务器,但它作为广播中间件,负责把事件“发出去”;真正建立长连接、推给浏览器的是另一层服务(比如 laravel-echo-server 或 soketi)。这个分离设计让 Laravel 能解耦广播逻辑和传输协议。
-
BROADCAST_DRIVER=redis时,Laravel 把事件序列化后写入 Redis 的laravel_database_notifications类似频道(实际是 Pub/Sub 模式) - 必须同时设置
QUEUE_CONNECTION=redis,否则ShouldBroadcast事件不会进队列,也就不会被消费和转发 - 如果只改了
BROADCAST_DRIVER却没启queue:work,你会看到日志里有事件 dispatch 成功,但前端永远没反应 - PHP 扩展
predis/predis或phpredis缺一不可,否则redis驱动初始化失败,报错Connection refused或Class "Predis\Client" not found
laravel-echo-server 启动后连不上?检查这四点
laravel-echo-server 是个 Node.js 进程,它监听 Redis 的 Pub/Sub,再通过 Socket.IO 把消息转给前端。它不处理认证,只做中转,所以出问题基本卡在这几个地方:
- 启动命令必须带配置文件:
laravel-echo-server start --config laravel-echo-server.json,否则它用默认空配置,authHost和databaseConfig.redis.port全错 - 前端
host必须和laravel-echo-server.json中的devServer.host一致,常见错误是前端写http://localhost:6001,而配置里authHost是https://myapp.com,导致鉴权请求跨域或 404 - 私有频道(
PrivateChannel)订阅前会发POST /broadcasting/auth请求,这个路由必须由 Laravel 提供,且routes/channels.php里对应频道的闭包返回true或用户信息数组,否则连接直接断开 - 防火墙或 Nginx 可能拦截 WebSocket 升级请求,确认响应头含
Upgrade: websocket和Connection: Upgrade,否则就是握手失败
用 soketi 替代 laravel-echo-server 的关键配置差异
soketi 是更轻量、更接近生产环境的选项,它原生支持 JWT 鉴权、多租户、HTTP/HTTPS,不需要额外写 auth 接口。但配置项位置和含义容易混淆:
-
PUSHER_HOST和PUSHER_PORT必须指向soketi容器地址,不是 Laravel 应用地址;例如 Docker 启动时映射了-p 6001:6001,那就要设PUSHER_HOST=127.0.0.1、PUSHER_PORT=6001 -
BROADCAST_DRIVER仍为pusher,不是soketi—— 因为 Soketi 声称 100% 兼容 Pusher 协议,Laravel 就当它是 Pusher -
PUSHER_APP_KEY、PUSHER_APP_SECRET必须和soketi启动时传入的环境变量严格一致,大小写敏感,漏一个字符都会认证失败,前端报错Access denied: Invalid key - 前端
cluster可任意设(如mt1),Soketi 不校验它;但 Laravel 的config/broadcasting.php中options.cluster必须存在,否则初始化Pusher实例时报Undefined index: cluster
前端 Laravel Echo 订阅失败的典型表现和定位方式
前端看不到消息,90% 不是后端没发,而是 Echo 没连上、没授权、或频道名对不上。别急着查队列日志,先看浏览器控制台和 Network:
- WebSocket 连接状态:在 Chrome DevTools 的
Network → WS标签页,看有没有ws://...连接,状态是不是101 Switching Protocols;如果是failed,说明握手失败,回头查soketi或laravel-echo-server日志 - 私有频道鉴权请求:在
Network → XHR里找/broadcasting/auth,看响应是200还是403;403多半是routes/channels.php里返回了false,或用户未登录(auth()->id()为空) - 频道名拼写:后端
new PrivateChannel('user.' . auth()->id())生成的是private-user.123,前端echo.private('user.123')必须完全一致,大小写、点号、前缀都不能错 - 事件名绑定:广播事件类里的
broadcastAs()方法如果设置了别名(如return 'notification.new'),前端就得用.listen('notification.new', ...),而不是类名UserNotificationEvent
最常被忽略的一点:所有广播事件的数据字段,必须是 public 属性或通过 broadcastWith() 显式返回。Laravel 默认只序列化 public 属性,如果你把消息存在 private $payload 里又没重写 broadcastWith(),前端收到的就是空对象。


















