在现代 Web 应用中,实时功能(如聊天、通知、动态数据更新)已成为标配。Laravel 的广播系统(Broadcasting)允许你使用 WebSocket 技术将服务器端的事件实时推送到前端,构建出响应迅速、交互流畅的实时应用。本章将带你掌握广播系统的配置、事件定义、频道授权以及前端集成。
Laravel 广播系统允许你在服务器端触发事件,并通过 WebSocket 将这些事件广播到客户端。它支持两种主要的广播驱动:
socket.io 或 laravel-websockets 包自建 WebSocket 服务器。
广播的事件需要实现 ShouldBroadcast 接口,Laravel 会自动将事件数据推送到指定的频道。
广播配置文件位于 config/broadcasting.php。你需要设置 BROADCAST_DRIVER 环境变量,并配置对应驱动的凭据。
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_APP_CLUSTER=mt1
安装 Pusher PHP SDK:
composer require pusher/pusher-php-server
BROADCAST_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
使用 Redis 驱动时,你需要一个 WebSocket 服务器来处理广播,例如 laravel-websockets 包:
composer require beyondcode/laravel-websockets
生成一个事件类并实现 ShouldBroadcast 接口:
php artisan make:event NewMessage
在事件类中,你需要指定广播的频道名称(broadcastOn 方法)以及可选的数据(broadcastWith)。
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public function __construct($message)
{
$this->message = $message;
}
// 指定广播频道(可以是字符串或 Channel 实例)
public function broadcastOn()
{
return new Channel('chat');
}
// 自定义广播数据(默认会序列化所有 public 属性)
public function broadcastWith()
{
return ['message' => $this->message, 'time' => now()->toDateTimeString()];
}
// 可选:指定广播队列连接
public function broadcastQueue()
{
return 'broadcast';
}
}
在控制器或其他地方,使用 event() 函数触发事件,广播将自动进行(如果驱动已配置):
use App\Events\NewMessage;
event(new NewMessage('Hello, world!'));
Laravel 支持三种频道类型:公共频道(public)、私有频道(private) 和 存在频道(presence)。私有频道和存在频道需要用户认证。
任何用户都可以订阅,无需授权。在 broadcastOn 中返回 new Channel('channel-name')。
只有授权用户才能订阅。频道名称以 private- 开头,并在 routes/channels.php 中定义授权回调。
// 在事件中
public function broadcastOn()
{
return new PrivateChannel('user.' . $this->user->id);
}
在 routes/channels.php 中授权:
Broadcast::channel('user.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
私有频道的扩展,除了订阅外,还能获取频道内其他用户的信息。频道名以 presence- 开头,授权回调需要返回用户信息数组。
// 事件中
public function broadcastOn()
{
return new PresenceChannel('chat.' . $this->chatId);
}
授权回调:
Broadcast::channel('chat.{chatId}', function ($user, $chatId) {
// 验证用户是否属于该聊天室
if ($user->canJoinChat($chatId)) {
return ['id' => $user->id, 'name' => $user->name];
}
return false;
});
Laravel Echo 是一个 JavaScript 库,用于订阅频道和监听事件。安装依赖:
npm install --save-dev laravel-echo pusher-js
或者使用 Redis + Socket.io:
npm install --save-dev laravel-echo socket.io-client
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
forceTLS: true,
});
// 公共频道
window.Echo.channel('chat')
.listen('NewMessage', (e) => {
console.log(e.message);
});
// 私有频道(需要认证)
window.Echo.private('user.' + userId)
.listen('NewMessage', (e) => {
console.log(e.message);
});
// 存在频道
window.Echo.join('chat.' + chatId)
.here((users) => {
console.log('当前在线用户:', users);
})
.joining((user) => {
console.log('用户加入:', user);
})
.leaving((user) => {
console.log('用户离开:', user);
})
.listen('NewMessage', (e) => {
console.log(e.message);
});
对于私有频道和存在频道,前端需要向服务器请求授权。Laravel 提供了 /broadcasting/auth 路由来处理授权。确保在 routes/api.php 或 routes/channels.php 中已启用。
如果你使用 Laravel Sanctum 或 Passport 进行 API 认证,需要在前端请求中包含认证令牌,Echo 会自动处理。
laravel-websockets 包让你可以在本地或服务器上运行 WebSocket 服务器,无需依赖 Pusher。安装后发布配置文件:
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
修改 .env:
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=local
PUSHER_APP_KEY=local
PUSHER_APP_SECRET=local
PUSHER_APP_CLUSTER=local
启动 WebSocket 服务器:
php artisan websockets:serve
前端 Echo 配置时,将 wsHost 和 wsPort 指向你的服务器地址。
user.{id}、chat.{chatId}。disconnect 事件并实现重连机制。Laravel 的广播系统让你能够轻松构建实时 Web 应用。通过配置驱动、定义广播事件、授权频道以及前端集成,你可以快速实现聊天、实时通知、在线用户列表等功能。结合队列和自建 WebSocket 服务器,甚至可以扩展到大规模实时应用。