本文目录导读:

Laravel 广播系统是处理实时事件推送的核心组件,下面从 核心概念 到 典型场景 再到 实战代码 来详细讲解。
核心概念(先理解再使用)
Laravel 广播分三层:
- 服务端事件:
ShouldBroadcast接口的 Event 类 - 频道(Channel):路由规则,决定谁可以监听
- 前端接收:Echo + Pusher/Soketi/WebSocket
关键点:广播不是“推消息给所有人”,而是“推消息给特定频道的订阅者”。
典型使用场景
场景 1:实时通知(最常见的用途)
适用业务:
- 用户收到新私信/评论/关注
- 订单状态变更(已付款 → 已发货)
- 后台审批通知
代码示例:
// 1. 创建事件
php artisan make:event OrderStatusChanged
// 2. 事件类
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class OrderStatusChanged implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $order;
public $oldStatus;
public $newStatus;
public function __construct(Order $order, $oldStatus, $newStatus)
{
$this->order = $order;
$this->oldStatus = $oldStatus;
$this->newStatus = $newStatus;
}
// 3. 定义广播的频道
public function broadcastOn()
{
// 该订单的用户专属私有频道
return new PrivateChannel('orders.' . $this->order->user_id);
}
// 可选:自定义广播名称
public function broadcastAs()
{
return 'status.updated';
}
}
// 4. 在业务逻辑中触发
public function updateOrderStatus(Order $order, $newStatus)
{
$oldStatus = $order->status;
$order->status = $newStatus;
$order->save();
// 触发广播事件(注意:会走队列,需配置 QUEUE_CONNECTION)
event(new OrderStatusChanged($order, $oldStatus, $newStatus));
}
// 5. 定义频道授权(在 routes/channels.php)
use App\Models\Order;
use App\Models\User;
Broadcast::channel('orders.{userId}', function (User $user, $userId) {
return $user->id === (int) $userId || $user->isAdmin();
});
前端接收:
// 使用 Laravel Echo 连接(假设是订单管理页面)
Echo.private(`orders.${userId}`)
.listen('OrderStatusChanged', (e) => {
// e.order, e.newStatus
showToast('您的订单状态已变为:' + e.newStatus);
updateOrderUI(e.order);
});
场景 2:在线协作/实时面板(Presence Channel 在场频道)
适用业务:
- 在线文档(多人编辑,显示谁在线)
- 实时仪表盘(数据监控中心)
- 聊天室/会议系统
代码示例:
// 事件:向在场频道广播谁加入了
class UserJoined implements ShouldBroadcast
{
public $user;
public $roomId;
public function __construct($user, $roomId)
{
$this->user = $user;
$this->roomId = $roomId;
}
public function broadcastOn()
{
// 在场频道需要指定房间 ID
return new PresenceChannel('room.' . $this->roomId);
}
}
授权现场频道:
// routes/channels.php
Broadcast::channel('room.{roomId}', function (User $user, $roomId) {
// 返回当前在线用户信息(数据会暴露给前端)
return $user->toArray();
});
前端监听:
Echo.join(`room.${roomId}`)
.here((users) => {
// 获取当前在线的所有用户列表(初始化面板)
displayOnlineUsers(users);
})
.joining((user) => {
// 当有人加入时
alert(`${user.name} 加入了房间`);
})
.leaving((user) => {
// 当有人离开时
alert(`${user.name} 离开了房间`);
});
场景 3:实时数据同步(直播间/股票行情/游戏)
适用业务:
- 股票价格更新、加密货币行情
- 直播间弹幕/礼物
- 外卖配送员位置实时更新
代码:
class StockPriceUpdated implements ShouldBroadcast
{
use Dispatchable, SerializesModels;
public $symbol;
public $price;
public function __construct($symbol, $price)
{
$this->symbol = $symbol;
$this->price = $price;
}
public function broadcastOn()
{
// 公共频道 - 不需要授权
return new Channel('stocks');
}
public function broadcastWith()
{
return [
'symbol' => $this->symbol,
'price' => $this->price,
'time' => now()->toDateTimeString()
];
}
}
// 前端订阅所有股票数据
Echo.channel('stocks')
.listen('StockPriceUpdated', (data) => {
updateStockChart(data.symbol, data.price);
});
场景 4:任务进度通知(后台长任务)
适用业务:
- 大数据导出/导入
- 视频转码(类似抖音上传后转码)
- 批量邮件发送
代码:
class ExportProgressUpdated implements ShouldBroadcast
{
public $exportId;
public $progress; // 0-100
public function __construct($exportId, $progress)
{
$this->exportId = $exportId;
$this->progress = $progress;
}
public function broadcastOn()
{
return new PrivateChannel('user.' . auth()->id() . '.exports.' . $this->exportId);
}
}
// 在导出 Job 的 handle() 中模拟进度
public function handle()
{
for ($i = 0; $i <= 100; $i += 10) {
$this->processChunk();
// 更新进度
event(new ExportProgressUpdated($this->exportId, $i));
sleep(2); // 模拟长任务
}
}
频道授权策略(重要!)
| 频道类型 | 类名 | 场景 | 是否需授权 |
|---|---|---|---|
| 公共频道 | Channel |
行情、广播通知 | 否 |
| 私有频道 | PrivateChannel |
用户专属消息、订单状态 | 是 |
| 在场频道 | PresenceChannel |
在线状态、实时协作 | 是 + 返回用户信息 |
生产环境配置建议
# .env 推荐配置 BROADCAST_DRIVER=pusher # 或 redis/soketi QUEUE_CONNECTION=redis # 广播事件必须走队列,否则同步执行会卡请求 # 使用 Pusher(第三方云服务) PUSHER_APP_ID=xxxx PUSHER_APP_KEY=xxxx PUSHER_APP_SECRET=xxxx PUSHER_APP_CLUSTER=mt1 # 或使用 Soketi(自建 WebSocket 服务) # BROADCAST_DRIVER=soketi # SOKETI_APP_ID=xxxx # SOKETI_APP_KEY=xxxx # SOKETI_APP_SECRET=xxxx # SOKETI_HOST=127.0.0.1 # SOKETI_PORT=6001
性能优化建议
- 必须用队列:所有 ShouldBroadcast 事件会自动入队,确保
QUEUE_CONNECTION=redis而不是sync。 - 避免广播大对象:
broadcastWith()只返回必要数据,不要传整个 User 模型(可能有密码等)。 - 频道粒度:不要使用全局频道应对百万连接,应拆分子频道(
user.1、user.2)。 - 限流:某些高频事件(如鼠标移动)可 1 秒合并广播一次。
- 监控:使用 Redis 的
MONITOR或 Pusher 控制台看消息频率。
调试技巧
// 测试广播事件 php artisan tinker >>> use App\Events\OrderStatusChanged; >>> event(new OrderStatusChanged(1, 'pending', 'paid'));
前端测试:
// 浏览器控制台
Echo.private('orders.1')
.listen('OrderStatusChanged', (e) => console.log(e));
如果你的业务是 实时性要求高、需要双向通信 的场景,Laravel 广播系统是最佳选择,如果有具体业务场景想咨询怎么做,可以发出来我给你针对性方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播