跳转到主要内容

什么是广播

WebSocket 让服务器可以实时向客户端推送数据。 Laravel 的广播用于把服务端事件通过 WebSocket 送达前端 JavaScript。 例如订单状态发生变化时,浏览器无需刷新即可立即看到更新。 Laravel 广播的优势在于:服务器端的事件名与数据可以直接分享给客户端。
广播基于 Laravel 事件系统。建议先了解事件与监听器的基础。

配置

新项目默认关闭广播。用 install:broadcasting 启用:
php artisan install:broadcasting
命令会提示你选择要使用的广播服务,并生成 config/broadcasting.phproutes/channels.php

Laravel Reverb

Laravel 11 及以后推荐使用官方 WebSocket 服务器 Laravel Reverb。 Reverb 支持自托管,无需外部服务即可实现实时通信。

安装

install:broadcasting--reverb 可一次完成 Composer / NPM 依赖安装与 .env 配置:
php artisan install:broadcasting --reverb
手动安装:
composer require laravel/reverb

php artisan reverb:install

.env 主要配置

BROADCAST_CONNECTION=reverb

REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secret
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"

启动 Reverb 服务器

php artisan reverb:start
生产环境请使用 Supervisor 等进程管理工具以守护方式运行。
广播事件通过队列处理,除 Reverb 外还需启动队列 worker:
php artisan queue:work

创建广播事件

生成事件类

php artisan make:event OrderShipmentStatusUpdated
给事件类实现 ShouldBroadcast 接口:
<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class OrderShipmentStatusUpdated implements ShouldBroadcast
{
    use InteractsWithSockets, SerializesModels;

    public function __construct(
        public Order $order,
    ) {}

    /** 返回要广播到的频道 */
    public function broadcastOn(): Channel
    {
        return new PrivateChannel('orders.' . $this->order->id);
    }
}
只要实现 ShouldBroadcast,事件触发时就会自动通过队列广播。

自定义广播数据

默认所有 public 属性都会成为广播 payload。若需精简数据,定义 broadcastWith
public function broadcastWith(): array
{
    return [
        'order_id' => $this->order->id,
        'status'   => $this->order->status,
    ];
}

自定义广播名称

默认使用类名作为事件名。可用 broadcastAs 自定义:
public function broadcastAs(): string
{
    return 'order.status.updated';
}
前端监听时使用 . 前缀以关闭 Laravel 命名空间前缀:
Echo.private(`orders.${orderId}`)
    .listen('.order.status.updated', (e) => {
        console.log(e);
    });

频道类型

频道说明
PublicChannel无需认证,任何人都可订阅
PrivatePrivateChannel仅认证用户,需要授权逻辑
PresencePresenceChannelPrivate 的扩展,可获取参与者列表
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;

// Public
public function broadcastOn(): Channel
{
    return new Channel('posts');
}

// Private
public function broadcastOn(): Channel
{
    return new PrivateChannel('orders.' . $this->order->id);
}

// Presence
public function broadcastOn(): Channel
{
    return new PresenceChannel('rooms.' . $this->room->id);
}
广播到多个频道用数组返回:
public function broadcastOn(): array
{
    return [
        new PrivateChannel('orders.' . $this->order->id),
        new Channel('admin.orders'),
    ];
}

频道授权

Private 与 Presence 频道在订阅前会在服务器端进行授权。

routes/channels.php

install:broadcasting 生成的 routes/channels.php 中定义授权回调:
use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
    return $user->id === Order::findOrNew($orderId)->user_id;
});
回调第一个参数是当前用户,之后是频道名中的通配符。 返回 true 或 truthy 值表示授权通过,false 则拒绝。
也可使用路由模型绑定。将频道名写为 orders.{order},回调会得到 Order 实例。
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
    return $user->id === $order->user_id;
});

使用频道类做授权

频道多时可用频道类组织:
php artisan make:channel OrderChannel
<?php

namespace App\Broadcasting;

use App\Models\Order;
use App\Models\User;

class OrderChannel
{
    public function join(User $user, Order $order): bool
    {
        return $user->id === $order->user_id;
    }
}
routes/channels.php 中注册:
use App\Broadcasting\OrderChannel;

Broadcast::channel('orders.{order}', OrderChannel::class);

触发事件

ShouldBroadcast 事件与普通事件的触发方式相同:
use App\Events\OrderShipmentStatusUpdated;

OrderShipmentStatusUpdated::dispatch($order);
只广播给他人(排除自己):
broadcast(new OrderShipmentStatusUpdated($order))->toOthers();
使用 toOthers 需要事件类 use InteractsWithSockets trait。

前端接收

配置 Laravel Echo

若使用 Reverb,在 resources/js/bootstrap.js 中设置 Echo:
npm install --save-dev laravel-echo pusher-js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'reverb',
    key: import.meta.env.VITE_REVERB_APP_KEY,
    wsHost: import.meta.env.VITE_REVERB_HOST,
    wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
    wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
    forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
});

监听事件

// Public
Echo.channel('posts')
    .listen('PostPublished', (e) => {
        console.log(e.post);
    });

// Private
Echo.private(`orders.${orderId}`)
    .listen('OrderShipmentStatusUpdated', (e) => {
        console.log(e.order);
    });

// Presence
Echo.join(`rooms.${roomId}`)
    .here((users) => {
        console.log('当前成员:', users);
    })
    .joining((user) => {
        console.log(user.name, '加入了');
    })
    .leaving((user) => {
        console.log(user.name, '离开了');
    })
    .listen('MessagePosted', (e) => {
        console.log(e.message);
    });

使用 React / Vue Hook

若使用官方 React / Vue 启动套件,可用专用 hook:
import { useEcho } from "@laravel/echo-react";

// Private
useEcho(
    `orders.${orderId}`,
    "OrderShipmentStatusUpdated",
    (e) => {
        console.log(e.order);
    },
);

// Public
import { useEchoPublic } from "@laravel/echo-react";

useEchoPublic("posts", "PostPublished", (e) => {
    console.log(e.post);
});
useEcho 会在组件卸载时自动离开频道。
前端构建前请确认 .env 中的 VITE_REVERB_* 已正确设置。
npm run build

实战示例:订单状态实时更新

1

启用广播

php artisan install:broadcasting --reverb
启动 Reverb 服务器与队列 worker:
php artisan reverb:start
php artisan queue:work
2

创建事件类

php artisan make:event OrderShipmentStatusUpdated
编辑 app/Events/OrderShipmentStatusUpdated.php
<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class OrderShipmentStatusUpdated implements ShouldBroadcast
{
    use InteractsWithSockets, SerializesModels;

    public function __construct(
        public Order $order,
    ) {}

    public function broadcastOn(): Channel
    {
        return new PrivateChannel('orders.' . $this->order->id);
    }

    public function broadcastWith(): array
    {
        return [
            'order_id' => $this->order->id,
            'status'   => $this->order->status,
        ];
    }
}
3

定义频道授权

use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('orders.{order}', function (User $user, Order $order) {
    return $user->id === $order->user_id;
});
4

触发事件

use App\Events\OrderShipmentStatusUpdated;

$order->update(['status' => 'shipped']);

OrderShipmentStatusUpdated::dispatch($order);
5

前端监听

Echo.private(`orders.${orderId}`)
    .listen('OrderShipmentStatusUpdated', (e) => {
        document.getElementById('status').textContent = e.status;
    });

下一步

Laravel Reverb

查看 Reverb 服务器的部署、生产运维与扩展详情。

队列与任务

广播依赖队列处理。了解队列的配置与运维。

事件与监听器

学习作为广播基础的 Laravel 事件系统。
最后修改于 2026年7月13日