Laravel怎么使用广播(Broadcasting)_Laravel实时通信教程【推送】

1次阅读

本地开发首选 redis,生产环境若无自建 redis 则选 pusher 或 laravel-websockets;需启用 broadcastserviceprovider、正确配置连接与路由、前端严格匹配频道名及权限,并用 broadcaston() 而非已废弃的 tobroadcast()。

Laravel怎么使用广播(Broadcasting)_Laravel实时通信教程【推送】

广播驱动选 redis 还是 pusher

本地开发用 redis 最省事,生产环境若没自建 Redis 或想跳过运维,pusher(或其开源替代 laravel-websockets)更稳妥。别用 log 驱动测逻辑——它不触发前端监听,容易误以为“代码跑通了”。

  • redis 要求已装 phpredis 扩展,且 config/broadcasting.phpredis 连接配置必须和 database.php 里一致,否则报 Connection refused
  • pusher 需在 .env 补全 PUSHER_APP_IDPUSHER_APP_KEYPUSHER_APP_SECRETPUSHER_APP_CLUSTER,漏一个就卡在 401 Unauthorized
  • 测试时先运行 php artisan queue:work(广播事件默认走队列),否则事件发出去但没人处理

BroadcastServiceProvider 必须手动启用

新版 Laravel 默认注释掉了 BroadcastServiceProvider 的注册,不打开它,Event(new XxxEvent) 根本不会推送到广播通道。这不是配置问题,是服务提供者根本没加载。

  • 打开 config/app.php,找到 providers 数组,取消注释这一行:AppProvidersBroadcastServiceProvider::class
  • 确认 app/Providers/BroadcastServiceProvider.php 中的 boot() 方法里调用了 Broadcast::routes(),否则 /broadcasting/auth 认证路由 404
  • 如果用 api 前缀路由,得显式传参:Broadcast::routes(['prefix' => 'api', 'middleware' => ['auth:api']])

前端监听不到事件?检查 channel 名称和权限

后端用 private-channel-name,前端就得写 private-channel-name,大小写、连字符、前缀一个都不能错;而且私有通道必须通过 /broadcasting/auth 验证,否则直接被拒绝。

  • 私有通道名必须以 private- 开头,如 private-user.123;前端用 echo 订阅时不能漏掉 private-echo.private('user.123') 是错的,得写 echo.private('private-user.123')
  • 认证失败时浏览器控制台会显示 403 Forbidden419 unknown status,此时看 routes/channels.php 里对应通道的闭包是否返回 true,且用户已登录
  • 使用 PresenceChannel 时,前端必须调用 .here().joining() 才能拿到在线用户列表,光监听事件没用

toBroadcast()broadcastOn() 别混用

事件类里定义广播目标,只用 broadcastOn() 就够了。toBroadcast() 是旧版写法(Laravel 5.x),现在调用它会静默忽略,但 IDE 可能不报错,导致通道订阅始终为空。

  • 正确写法:public function broadcastOn() { return new PrivateChannel('user.' . $this->user->id); }
  • 错误写法:public function toBroadcast() { ... } —— 这个方法已被废弃,Laravel 9+ 完全不识别
  • 如果事件要推多个通道,返回数组:return [new PrivateChannel(...), new Channel(...)],别用逗号拼字符串
  • 事件属性默认全部广播,敏感字段(如 $this->user->password)必须在 $broadcastWhenshouldBroadcastNow() 里过滤,否则泄露

广播不是“发完就完”,从事件触发、队列消费、Redis 写入、到前端收到,中间任何一环断开都看不到效果。最常卡在队列没跑、频道名不匹配、或认证路由没配对——这三处挨个敲一遍 dd() 或日志,比重读文档快得多。

text=ZqhQzanResources