跳至内容

广播

介绍

在许多现代 Web 应用中,WebSocket 用于实现实时更新的用户界面。当服务器上的数据更新时,通常会通过 WebSocket 连接发送一条消息,供客户端处理。WebSocket 提供了一种更高效的替代方案,无需持续轮询应用服务器以获取应反映在 UI 中的数据更改。

例如,假设您的应用程序能够将用户数据导出到 CSV 文件并通过电子邮件发送给他们。但是,创建此 CSV 文件需要几分钟时间,因此您选择在队列作业中创建并邮寄 CSV 文件。当 CSV 文件创建完成并邮寄给用户后,我们可以使用事件广播来调度一个App\Events\UserDataExported事件,该事件会被应用程序的 JavaScript 接收。接收到该事件后,我们可以向用户显示一条消息,告知他们 CSV 文件已通过电子邮件发送给他们,而无需用户刷新页面。

为了帮助您构建这些类型的功能,Laravel 可以轻松地通过 WebSocket 连接“广播”服务器端 Laravel事件。广播 Laravel 事件允许您在服务器端 Laravel 应用程序和客户端 JavaScript 应用程序之间共享相同的事件名称和数据。

广播背后的核心概念很简单:客户端连接到前端的指定频道,而你的 Laravel 应用程序将事件广播到后端的这些频道。这些事件可以包含你希望提供给前端的任何其他数据。

支持的驱动程序

默认情况下,Laravel 包含三个服务器端广播驱动程序供您选择:Laravel ReverbPusher ChannelsAbly

在深入研究事件广播之前,请确保您已阅读 Laravel 关于事件和监听器的文档。

快速入门

默认情况下,新的 Laravel 应用程序中不启用广播。你可以使用install:broadcastingArtisan 命令启用广播:

1php artisan install:broadcasting

install:broadcasting命令会Prompts您选择要使用的事件广播服务。此外,它还会创建config/broadcasting.php配置文件以及routes/channels.php用于注册应用程序广播授权路由和回调的文件。

Laravel 支持多种开箱即用的广播驱动程序:Laravel ReverbPusher ChannelsAbly以及log用于本地开发和调试的驱动程序。此外,null还包含一个驱动程序,允许您在测试期间禁用广播。配置文件中为每个驱动程序都提供了相应的配置示例config/broadcasting.php

应用程序的所有事件广播配置都存储在config/broadcasting.php配置文件中。如果您的应用程序中不存在此文件,请不要担心;它会在您运行install:broadcastingArtisan 命令时创建。

后续步骤

启用事件广播后,您就可以了解有关定义广播事件监听事件的更多信息。如果您使用的是 Laravel 的 React 或 Vue入门套件,则可以使用 Echo 的useEcho 钩子来监听事件

在广播任何事件之前,您应该首先配置并运行队列工作器。所有事件广播均通过队列作业完成,因此应用程序的响应时间不会受到广播事件的严重影响。

服务器端安装

要开始使用 Laravel 的事件广播,我们需要在 Laravel 应用程序中进行一些配置并安装一些包。

事件广播由服务器端的广播驱动程序完成,该驱动程序会广播您的 Laravel 事件,以便 Laravel Echo(一个 JavaScript 库)可以在浏览器客户端中接收它们。别担心 - 我们将逐步介绍安装过程的每个部分。

Reverb

要在使用 Reverb 作为事件广播器时快速启用 Laravel 的广播功能,请install:broadcasting使用该选项调用 Artisan 命令。此 Artisan 命令将安装 Reverb 所需的 Composer 和 NPM 软件包,并使用相应的变量--reverb更新应用程序文件:.env

1php artisan install:broadcasting --reverb

手动安装

运行该install:broadcasting命令时,系统将Prompts你安装Laravel Reverb。当然,你也可以使用 Composer 包管理器手动安装 Reverb :

1composer require laravel/reverb

安装软件包后,您可以运行 Reverb 的安装命令来发布配置,添加 Reverb 所需的环境变量,并在应用程序中启用事件广播:

1php artisan reverb:install

您可以在Reverb 文档中找到详细的 Reverb 安装和使用说明

推进器通道

要在使用 Pusher 作为事件广播器的同时快速启用 Laravel 的广播功能,请install:broadcasting使用该--pusher选项调用 Artisan 命令。此 Artisan 命令将Prompts您输入 Pusher 凭据,安装 Pusher PHP 和 JavaScript SDK,并.env使用相应的变量更新应用程序文件:

1php artisan install:broadcasting --pusher

手动安装

要手动安装 Pusher 支持,您应该使用 Composer 包管理器安装 Pusher Channels PHP SDK:

1composer require pusher/pusher-php-server

接下来,您应该在配置文件中配置 Pusher Channels 凭证config/broadcasting.php。此文件中已包含 Pusher Channels 配置示例,可让您快速指定密钥、机密和应用程序 ID。通常,您应该在应用程序的.env文件中配置 Pusher Channels 凭证:

1PUSHER_APP_ID="your-pusher-app-id"
2PUSHER_APP_KEY="your-pusher-key"
3PUSHER_APP_SECRET="your-pusher-secret"
4PUSHER_HOST=
5PUSHER_PORT=443
6PUSHER_SCHEME="https"
7PUSHER_APP_CLUSTER="mt1"

config/broadcasting.php文件的pusher配置还允许您指定optionsChannels 支持的其他内容,例如集群。

然后,在应用程序的文件中将BROADCAST_CONNECTION环境变量设置为pusher.env

1BROADCAST_CONNECTION=pusher

最后,您已准备好安装和配置Laravel Echo,它将在客户端接收广播事件。

巧妙地

以下文档讨论了如何在“推送器兼容”模式下使用 Ably。不过,Ably 团队推荐并维护了一个能够充分利用 Ably 独特功能的广播器和 Echo 客户端。有关使用 Ably 维护的驱动程序的更多信息,请参阅 Ably 的 Laravel 广播器文档

要在使用Ably作为事件广播器的同时快速启用 Laravel 的广播功能,请install:broadcasting使用选项调用 Artisan 命令--ably。此 Artisan 命令将Prompts您输入 Ably 凭据,安装 Ably PHP 和 JavaScript SDK,并.env使用相应的变量更新应用程序文件:

1php artisan install:broadcasting --ably

在继续操作之前,您需要在 Ably 应用程序设置中启用 Pusher 协议支持。您可以在 Ably 应用程序设置面板的“协议适配器设置”部分中启用此功能。

手动安装

要手动安装 Ably 支持,您应该使用 Composer 包管理器安装 Ably PHP SDK:

1composer require ably/ably-php

接下来,您应该在config/broadcasting.php配置文件中配置您的 Ably 凭据。此文件中已包含一个 Ably 配置示例,可让您快速指定密钥。通常,此值应通过ABLY_KEY 环境变量设置:

1ABLY_KEY=your-ably-key

然后,在应用程序的文件中将BROADCAST_CONNECTION环境变量设置为ably.env

1BROADCAST_CONNECTION=ably

最后,您已准备好安装和配置Laravel Echo,它将在客户端接收广播事件。

客户端安装

Reverb

Laravel Echo是一个 JavaScript 库,它可以轻松订阅频道并监听服务器端广播驱动程序广播的事件。

通过 Artisan 命令安装 Laravel Reverb 时install:broadcasting,Reverb 和 Echo 的脚手架和配置将自动注入到你的应用程序中。但是,如果你希望手动配置 Laravel Echo,可以按照以下说明进行操作。

手动安装

要为应用程序的前端手动配置 Laravel Echo,请首先安装该pusher-js软件包,因为 Reverb 使用 Pusher 协议进行 WebSocket 订阅、频道和消息:

1npm install --save-dev laravel-echo pusher-js

resources/js/bootstrap.js安装 Echo 后,您就可以在应用程序的 JavaScript 中创建一个新的 Echo 实例了。执行此操作的最佳位置是Laravel 框架自带文件的底部:

1import Echo from 'laravel-echo';
2 
3import Pusher from 'pusher-js';
4window.Pusher = Pusher;
5 
6window.Echo = new Echo({
7 broadcaster: 'reverb',
8 key: import.meta.env.VITE_REVERB_APP_KEY,
9 wsHost: import.meta.env.VITE_REVERB_HOST,
10 wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
11 wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
12 forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
13 enabledTransports: ['ws', 'wss'],
14});
1import { configureEcho } from "@laravel/echo-react";
2 
3configureEcho({
4 broadcaster: "reverb",
5 // key: import.meta.env.VITE_REVERB_APP_KEY,
6 // wsHost: import.meta.env.VITE_REVERB_HOST,
7 // wsPort: import.meta.env.VITE_REVERB_PORT,
8 // wssPort: import.meta.env.VITE_REVERB_PORT,
9 // forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
10 // enabledTransports: ['ws', 'wss'],
11});
1import { configureEcho } from "@laravel/echo-vue";
2 
3configureEcho({
4 broadcaster: "reverb",
5 // key: import.meta.env.VITE_REVERB_APP_KEY,
6 // wsHost: import.meta.env.VITE_REVERB_HOST,
7 // wsPort: import.meta.env.VITE_REVERB_PORT,
8 // wssPort: import.meta.env.VITE_REVERB_PORT,
9 // forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
10 // enabledTransports: ['ws', 'wss'],
11});

接下来,您应该编译应用程序的资产:

1npm run build

Laravel Echoreverb广播器需要 laravel-echo v1.16.0+。

推进器通道

Laravel Echo是一个 JavaScript 库,它可以轻松订阅频道并监听服务器端广播驱动程序广播的事件。

通过install:broadcasting --pusherArtisan 命令安装广播支持时,Pusher 和 Echo 的脚手架和配置将自动注入到你的应用程序中。但是,如果你希望手动配置 Laravel Echo,可以按照以下说明进行操作。

手动安装

要为应用程序的前端手动配置 Laravel Echo,首先安装laravel-echopusher-js包,它们利用 Pusher 协议进行 WebSocket 订阅、频道和消息:

1npm install --save-dev laravel-echo pusher-js

安装 Echo 后,您就可以在应用程序resources/js/bootstrap.js文件中创建一个新的 Echo 实例:

1import Echo from 'laravel-echo';
2 
3import Pusher from 'pusher-js';
4window.Pusher = Pusher;
5 
6window.Echo = new Echo({
7 broadcaster: 'pusher',
8 key: import.meta.env.VITE_PUSHER_APP_KEY,
9 cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
10 forceTLS: true
11});
1import { configureEcho } from "@laravel/echo-react";
2 
3configureEcho({
4 broadcaster: "pusher",
5 // key: import.meta.env.VITE_PUSHER_APP_KEY,
6 // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
7 // forceTLS: true,
8 // wsHost: import.meta.env.VITE_PUSHER_HOST,
9 // wsPort: import.meta.env.VITE_PUSHER_PORT,
10 // wssPort: import.meta.env.VITE_PUSHER_PORT,
11 // enabledTransports: ["ws", "wss"],
12});
1import { configureEcho } from "@laravel/echo-vue";
2 
3configureEcho({
4 broadcaster: "pusher",
5 // key: import.meta.env.VITE_PUSHER_APP_KEY,
6 // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
7 // forceTLS: true,
8 // wsHost: import.meta.env.VITE_PUSHER_HOST,
9 // wsPort: import.meta.env.VITE_PUSHER_PORT,
10 // wssPort: import.meta.env.VITE_PUSHER_PORT,
11 // enabledTransports: ["ws", "wss"],
12});

接下来,您应该在应用程序文件中为 Pusher 环境变量定义适当的值.env。如果文件中尚不存在这些变量.env,则应添加它们:

1PUSHER_APP_ID="your-pusher-app-id"
2PUSHER_APP_KEY="your-pusher-key"
3PUSHER_APP_SECRET="your-pusher-secret"
4PUSHER_HOST=
5PUSHER_PORT=443
6PUSHER_SCHEME="https"
7PUSHER_APP_CLUSTER="mt1"
8 
9VITE_APP_NAME="${APP_NAME}"
10VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
11VITE_PUSHER_HOST="${PUSHER_HOST}"
12VITE_PUSHER_PORT="${PUSHER_PORT}"
13VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
14VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

根据应用程序的需求调整 Echo 配置后,您可以编译应用程序的资产:

1npm run build

使用现有的客户端实例

如果您已经有一个预先配置的 Pusher Channels 客户端实例并希望 Echo 使用,您可以通过client配置选项将其传递给 Echo:

1import Echo from 'laravel-echo';
2import Pusher from 'pusher-js';
3 
4const options = {
5 broadcaster: 'pusher',
6 key: import.meta.env.VITE_PUSHER_APP_KEY
7}
8 
9window.Echo = new Echo({
10 ...options,
11 client: new Pusher(options.key, options)
12});

巧妙地

以下文档讨论了如何在“推送器兼容”模式下使用 Ably。不过,Ably 团队推荐并维护了一个能够充分利用 Ably 独特功能的广播器和 Echo 客户端。有关使用 Ably 维护的驱动程序的更多信息,请参阅 Ably 的 Laravel 广播器文档

Laravel Echo是一个 JavaScript 库,它可以轻松订阅频道并监听服务器端广播驱动程序广播的事件。

通过install:broadcasting --ablyArtisan 命令安装广播支持时,Ably 和 Echo 的脚手架和配置将自动注入到您的应用程序中。但是,如果您希望手动配置 Laravel Echo,可以按照以下说明进行操作。

手动安装

要为应用程序的前端手动配置 Laravel Echo,首先安装laravel-echopusher-js包,它们利用 Pusher 协议进行 WebSocket 订阅、频道和消息:

1npm install --save-dev laravel-echo pusher-js

在继续操作之前,您需要在 Ably 应用程序设置中启用 Pusher 协议支持。您可以在 Ably 应用程序设置面板的“协议适配器设置”部分中启用此功能。

安装 Echo 后,您就可以在应用程序resources/js/bootstrap.js文件中创建一个新的 Echo 实例:

1import Echo from 'laravel-echo';
2 
3import Pusher from 'pusher-js';
4window.Pusher = Pusher;
5 
6window.Echo = new Echo({
7 broadcaster: 'pusher',
8 key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
9 wsHost: 'realtime-pusher.ably.io',
10 wsPort: 443,
11 disableStats: true,
12 encrypted: true,
13});
1import { configureEcho } from "@laravel/echo-react";
2 
3configureEcho({
4 broadcaster: "ably",
5 // key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
6 // wsHost: "realtime-pusher.ably.io",
7 // wsPort: 443,
8 // disableStats: true,
9 // encrypted: true,
10});
1import { configureEcho } from "@laravel/echo-vue";
2 
3configureEcho({
4 broadcaster: "ably",
5 // key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
6 // wsHost: "realtime-pusher.ably.io",
7 // wsPort: 443,
8 // disableStats: true,
9 // encrypted: true,
10});

您可能已经注意到我们的 Ably Echo 配置引用了一个VITE_ABLY_PUBLIC_KEY环境变量。该变量的值应该是您的 Ably 公钥。您的公钥是 Ably 密钥中:字符之前的部分。

根据您的需要调整 Echo 配置后,您可以编译应用程序的资产:

1npm run dev

概念概述

Laravel 的事件广播功能允许您使用基于驱动程序的 WebSocket 方法将服务器端 Laravel 事件广播到客户端 JavaScript 应用程序。目前,Laravel 已集成Laravel ReverbPusher ChannelsAbly驱动程序。您可以使用Laravel Echo JavaScript 包在客户端轻松使用这些事件

事件通过“频道”进行广播,频道可以指定为公共频道或私有频道。任何访问您应用的访客都可以订阅公共频道,无需任何身份验证或授权;但是,要订阅私有频道,用户必须经过身份验证并获得授权才能收听该频道。

使用示例应用程序

在深入研究事件广播的每个组件之前,让我们以电子商务商店为例进行高层次的概述。

在我们的应用中,假设有一个页面允许用户查看订单的配送状态。同时假设OrderShipmentStatusUpdated当应用处理配送状态更新时会触发一个事件:

1use App\Events\OrderShipmentStatusUpdated;
2 
3OrderShipmentStatusUpdated::dispatch($order);

界面ShouldBroadcast

当用户查看订单时,我们不希望他们刷新页面来查看状态更新。相反,我们希望在订单创建时就将更新广播到应用程序。因此,我们需要OrderShipmentStatusUpdatedShouldBroadcast接口标记该事件。这将指示 Laravel 在触发该事件时广播该事件:

1<?php
2 
3namespace App\Events;
4 
5use App\Models\Order;
6use Illuminate\Broadcasting\Channel;
7use Illuminate\Broadcasting\InteractsWithSockets;
8use Illuminate\Broadcasting\PresenceChannel;
9use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
10use Illuminate\Queue\SerializesModels;
11 
12class OrderShipmentStatusUpdated implements ShouldBroadcast
13{
14 /**
15 * The order instance.
16 *
17 * @var \App\Models\Order
18 */
19 public $order;
20}

ShouldBroadcast接口要求我们的事件定义一个broadcastOn方法。此方法负责返回事件应在其上广播的频道。此方法的空存根已在生成的事件类中定义,因此我们只需填写其详细信息。我们只希望订单的创建者能够查看状态更新,因此我们将在与订单绑定的私有频道上广播该事件:

1use Illuminate\Broadcasting\Channel;
2use Illuminate\Broadcasting\PrivateChannel;
3 
4/**
5 * Get the channel the event should broadcast on.
6 */
7public function broadcastOn(): Channel
8{
9 return new PrivateChannel('orders.'.$this->order->id);
10}

如果您希望该事件在多个频道上广播,您可以返回array

1use Illuminate\Broadcasting\PrivateChannel;
2 
3/**
4 * Get the channels the event should broadcast on.
5 *
6 * @return array<int, \Illuminate\Broadcasting\Channel>
7 */
8public function broadcastOn(): array
9{
10 return [
11 new PrivateChannel('orders.'.$this->order->id),
12 // ...
13 ];
14}

授权渠道

请记住,用户必须获得授权才能监听私人频道。我们可以在应用程序routes/channels.php文件中定义频道授权规则。在此示例中,我们需要验证任何尝试监听私人orders.1频道的用户是否确实是订单的创建者:

1use App\Models\Order;
2use App\Models\User;
3 
4Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
5 return $user->id === Order::findOrNew($orderId)->user_id;
6});

channel方法接受两个参数:频道名称和返回truefalse指示用户是否有权在该频道上收听的回调。

所有授权回调都会接收当前已验证的用户作为其第一个参数,并将任何其他通配符参数作为其后续参数。在此示例中,我们使用{orderId}占位符来指示频道名称的“ID”部分是通配符。

监听事件广播

接下来,剩下的就是在我们的 JavaScript 应用程序中监听事件。我们可以使用Laravel Echo来实现。Laravel Echo 内置的 React 和 Vue hooks 使其易于上手,并且默认情况下,事件的所有公共属性都将包含在广播事件中:

1import { useEcho } from "@laravel/echo-react";
2 
3useEcho(
4 `orders.${orderId}`,
5 "OrderShipmentStatusUpdated",
6 (e) => {
7 console.log(e.order);
8 },
9);
1<script setup lang="ts">
2import { useEcho } from "@laravel/echo-vue";
3 
4useEcho(
5 `orders.${orderId}`,
6 "OrderShipmentStatusUpdated",
7 (e) => {
8 console.log(e.order);
9 },
10);
11</script>

定义广播事件

要通知 Laravel 广播指定事件,您必须Illuminate\Contracts\Broadcasting\ShouldBroadcast在事件类上实现相应的接口。此接口已导入到框架生成的所有事件类中,因此您可以轻松地将其添加到任何事件中。

ShouldBroadcast接口只需实现一个方法:broadcastOn。该broadcastOn方法应返回一个频道或频道数组,用于广播事件。频道应为ChannelPrivateChannel或 的实例PresenceChannel。 的实例Channel表示任何用户均可订阅的公共频道,而PrivateChannels和 的实例表示需要频道授权PresenceChannels的私有频道

1<?php
2 
3namespace App\Events;
4 
5use App\Models\User;
6use Illuminate\Broadcasting\Channel;
7use Illuminate\Broadcasting\InteractsWithSockets;
8use Illuminate\Broadcasting\PresenceChannel;
9use Illuminate\Broadcasting\PrivateChannel;
10use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
11use Illuminate\Queue\SerializesModels;
12 
13class ServerCreated implements ShouldBroadcast
14{
15 use SerializesModels;
16 
17 /**
18 * Create a new event instance.
19 */
20 public function __construct(
21 public User $user,
22 ) {}
23 
24 /**
25 * Get the channels the event should broadcast on.
26 *
27 * @return array<int, \Illuminate\Broadcasting\Channel>
28 */
29 public function broadcastOn(): array
30 {
31 return [
32 new PrivateChannel('user.'.$this->user->id),
33 ];
34 }
35}

实现该接口后ShouldBroadcast,您只需像平常一样触发该事件即可。触发该事件后,队列任务将自动使用您指定的广播驱动程序广播该事件。

广播名称

默认情况下,Laravel 将使用事件的类名来广播该事件。但是,您可以通过broadcastAs在事件上定义方法来自定义广播名称:

1/**
2 * The event's broadcast name.
3 */
4public function broadcastAs(): string
5{
6 return 'server.created';
7}

如果你使用该方法自定义广播名称broadcastAs,则应确保以一个前导.字符注册监听器。这将指示 Echo 不将应用程序的命名空间添加到事件的前面:

1.listen('.server.created', function (e) {
2 // ...
3});

广播数据

当事件被广播时,其所有public属性都会自动序列化并作为事件的有效负载进行广播,从而允许你在 JavaScript 应用程序中访问其任何公共数据。例如,如果你的事件有一个$user包含 Eloquent 模型的公共属性,则该事件的广播有效负载将是:

1{
2 "user": {
3 "id": 1,
4 "name": "Patrick Stewart"
5 ...
6 }
7}

但是,如果您希望对广播负载进行更细粒度的控制,可以broadcastWith向事件添加一个方法。此方法应返回您希望作为事件负载广播的数据数组:

1/**
2 * Get the data to broadcast.
3 *
4 * @return array<string, mixed>
5 */
6public function broadcastWith(): array
7{
8 return ['id' => $this->user->id];
9}

广播队列

默认情况下,每个广播事件都会被放置在配置文件中指定的默认队列连接的默认队列中。您可以通过在事件类中定义和属性queue.php来自定义广播器使用的队列连接和名称:connectionqueue

1/**
2 * The name of the queue connection to use when broadcasting the event.
3 *
4 * @var string
5 */
6public $connection = 'redis';
7 
8/**
9 * The name of the queue on which to place the broadcasting job.
10 *
11 * @var string
12 */
13public $queue = 'default';

broadcastQueue或者,您可以通过在事件上定义方法来自定义队列名称:

1/**
2 * The name of the queue on which to place the broadcasting job.
3 */
4public function broadcastQueue(): string
5{
6 return 'default';
7}

如果您希望使用sync队列而不是默认队列驱动程序来广播事件,则可以实现ShouldBroadcastNow接口而不是ShouldBroadcast

1<?php
2 
3namespace App\Events;
4 
5use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
6 
7class OrderShipmentStatusUpdated implements ShouldBroadcastNow
8{
9 // ...
10}

播出条件

有时,您希望仅在给定条件成立时才广播事件。您可以通过broadcastWhen向事件类添加方法来定义这些条件:

1/**
2 * Determine if this event should broadcast.
3 */
4public function broadcastWhen(): bool
5{
6 return $this->order->value > 100;
7}

广播和数据库交易

当广播事件在数据库事务中被调度时,它们可能会在数据库事务提交之前就被队列处理。发生这种情况时,您在数据库事务期间对模型或数据库记录所做的任何更新可能尚未反映在数据库中。此外,在事务中创建的任何模型或数据库记录可能都不存在于数据库中。如果您的事件依赖于这些模型,则在处理广播事件的作业时可能会发生意外错误。

如果您的队列连接的after_commit配置选项设置为,您仍然可以通过实现事件类上的接口false来指示在提交所有打开的数据库事务后应分派特定的广播事件:ShouldDispatchAfterCommit

1<?php
2 
3namespace App\Events;
4 
5use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
6use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
7use Illuminate\Queue\SerializesModels;
8 
9class ServerCreated implements ShouldBroadcast, ShouldDispatchAfterCommit
10{
11 use SerializesModels;
12}

授权渠道

私有频道需要您授权当前已验证的用户能够实际收听该频道。具体方法是向 Laravel 应用程序发送一个包含频道名称的 HTTP 请求,并允许应用程序判断用户是否可以收听该频道。使用Laravel Echo时,系统会自动发出授权订阅私有频道的 HTTP 请求。

启用广播后,Laravel 会自动注册/broadcasting/auth路由来处理授权请求。该/broadcasting/auth路由会自动放置在web中间件组中。

定义授权回调

接下来,我们需要定义逻辑来判断当前已认证用户是否可以监听指定频道。这在Artisan 命令routes/channels.php创建的文件中完成install:broadcasting。在这个文件中,你可以使用以下Broadcast::channel方法来注册频道授权回调:

1use App\Models\User;
2 
3Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
4 return $user->id === Order::findOrNew($orderId)->user_id;
5});

channel方法接受两个参数:频道名称和返回truefalse指示用户是否有权在该频道上收听的回调。

所有授权回调都会接收当前已验证的用户作为其第一个参数,并将任何其他通配符参数作为其后续参数。在此示例中,我们使用{orderId}占位符来指示频道名称的“ID”部分是通配符。

您可以使用 Artisan 命令查看应用程序的广播授权回调列表channel:list

1php artisan channel:list

授权回调模型绑定

与 HTTP 路由类似,通道路由也可以利用隐式和显式路由模型绑定。例如,除了接收字符串或数字形式的订单 ID,你还可以请求一个实际的Order模型实例:

1use App\Models\Order;
2use App\Models\User;
3 
4Broadcast::channel('orders.{order}', function (User $user, Order $order) {
5 return $user->id === $order->user_id;
6});

与 HTTP 路由模型绑定不同,通道模型绑定不支持自动隐式模型绑定范围界定。不过,这很少会成为问题,因为大多数通道可以基于单个模型的唯一主键来限定范围。

授权回调认证

私有广播频道和在线状态广播频道通过应用默认的身份验证守卫对当前用户进行身份验证。如果用户未通过身份验证,频道授权将被自动拒绝,并且授权回调不会被执行。但是,您可以根据需要指定多个自定义守卫来对传入的请求进行身份验证:

1Broadcast::channel('channel', function () {
2 // ...
3}, ['guards' => ['web', 'admin']]);

定义通道类别

如果您的应用程序使用许多不同的通道,routes/channels.php文件可能会变得非常庞大。因此,您可以使用通道类来授权通道,而不是使用闭包。要生成通道类,请使用make:channelArtisan 命令。此命令会在目录中放置一个新的通道类App/Broadcasting

1php artisan make:channel OrderChannel

接下来,在您的文件中注册您的频道routes/channels.php

1use App\Broadcasting\OrderChannel;
2 
3Broadcast::channel('orders.{order}', OrderChannel::class);

最后,您可以将频道的授权逻辑放在频道类的join方法中。此join方法将包含您通常放在频道授权闭包中的逻辑。您还可以利用频道模型绑定:

1<?php
2 
3namespace App\Broadcasting;
4 
5use App\Models\Order;
6use App\Models\User;
7 
8class OrderChannel
9{
10 /**
11 * Create a new channel instance.
12 */
13 public function __construct() {}
14 
15 /**
16 * Authenticate the user's access to the channel.
17 */
18 public function join(User $user, Order $order): array|bool
19 {
20 return $user->id === $order->user_id;
21 }
22}

与 Laravel 中的许多其他类一样,通道类将由服务容器 自动解析。因此,您可以在通道的构造函数中键入所需的任何依赖项。

广播Events

定义事件并用ShouldBroadcast接口标记后,只需使用事件的 dispatch 方法触发该事件即可。事件调度器会注意到该事件已用ShouldBroadcast接口标记,并将该事件加入队列进行广播:

1use App\Events\OrderShipmentStatusUpdated;
2 
3OrderShipmentStatusUpdated::dispatch($order);

仅限他人

在构建使用事件广播的应用程序时,有时可能需要将事件广播给指定频道的所有订阅者(当前用户除外)。您可以使用broadcastHelpers类和toOthers方法来实现:

1use App\Events\OrderShipmentStatusUpdated;
2 
3broadcast(new OrderShipmentStatusUpdated($update))->toOthers();

为了更好地理解何时需要使用该toOthers方法,我们设想一个任务列表应用,用户可以通过输入任务名称来创建新任务。要创建任务,你的应用可能会向一个/taskURL 发出请求,该 URL 广播任务创建的消息,并返回新任务的 JSON 格式。当你的 JavaScript 应用收到来自终端的响应时,它可能会直接将新任务插入到其任务列表中,如下所示:

1axios.post('/task', task)
2 .then((response) => {
3 this.tasks.push(response.data);
4 });

但是,请记住,我们还会广播任务的创建事件。如果您的 JavaScript 应用程序也监听此事件以便将任务添加到任务列表中,则列表中会出现重复的任务:一个来自终端,一个来自广播。您可以使用该toOthers方法指示广播器不向当前用户广播该事件来解决这个问题。

您的事件必须使用该Illuminate\Broadcasting\InteractsWithSockets特征才能调用该toOthers方法。

配置

初始化 Laravel Echo 实例时,会为连接分配一个套接字 ID。如果您使用全局Axios实例从 JavaScript 应用程序发出 HTTP 请求,则套接字 ID 将自动作为X-Socket-ID标头附加到每个发出的请求中。然后,当您调用该toOthers方法时,Laravel 将从标头中提取套接字 ID,并指示广播器不向任何具有该套接字 ID 的连接进行广播。

如果您没有使用全局 Axios 实例,则需要手动配置 JavaScript 应用程序,以便将X-Socket-ID标头随所有发出的请求一起发送。您可以使用以下命令获取套接字 ID Echo.socketId

1var socketId = Echo.socketId();

自定义连接

如果您的应用程序与多个广播连接进行交互,并且您想要使用默认广播器以外的广播器来广播事件,则可以使用该via方法指定将事件推送到哪个连接:

1use App\Events\OrderShipmentStatusUpdated;
2 
3broadcast(new OrderShipmentStatusUpdated($update))->via('pusher');

broadcastVia或者,你也可以通过调用事件构造函数中的方法来指定事件的广播连接。不过,在执行此操作之前,你应该确保事件类使用了以下InteractsWithBroadcasting特征:

1<?php
2 
3namespace App\Events;
4 
5use Illuminate\Broadcasting\Channel;
6use Illuminate\Broadcasting\InteractsWithBroadcasting;
7use Illuminate\Broadcasting\InteractsWithSockets;
8use Illuminate\Broadcasting\PresenceChannel;
9use Illuminate\Broadcasting\PrivateChannel;
10use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
11use Illuminate\Queue\SerializesModels;
12 
13class OrderShipmentStatusUpdated implements ShouldBroadcast
14{
15 use InteractsWithBroadcasting;
16 
17 /**
18 * Create a new event instance.
19 */
20 public function __construct()
21 {
22 $this->broadcastVia('pusher');
23 }
24}

匿名事件

有时,你可能希望将一个简单的事件广播到应用程序的前端,而无需创建专门的事件类。为了满足这种情况,Broadcast外观层允许你广播“匿名事件”:

1Broadcast::on('orders.'.$order->id)->send();

上面的例子将广播以下事件:

1{
2 "event": "AnonymousEvent",
3 "data": "[]",
4 "channel": "orders.1"
5}

使用aswith方法,您可以自定义事件的名称和数据:

1Broadcast::on('orders.'.$order->id)
2 ->as('OrderPlaced')
3 ->with($order)
4 ->send();

上面的例子将广播如下事件:

1{
2 "event": "OrderPlaced",
3 "data": "{ id: 1, total: 100 }",
4 "channel": "orders.1"
5}

如果您想在私人或在线频道上广播匿名事件,您可以使用privatepresence方法:

1Broadcast::private('orders.'.$order->id)->send();
2Broadcast::presence('channels.'.$channel->id)->send();

使用 方法来广播匿名事件,send会将该事件调度到应用程序的队列中进行处理。但是,如果您想立即广播该事件,可以使用sendNow方法来广播:

1Broadcast::on('orders.'.$order->id)->sendNow();

要将事件广播给除当前已验证用户之外的所有频道订阅者,您可以调用该toOthers方法:

1Broadcast::on('orders.'.$order->id)
2 ->toOthers()
3 ->send();

接收广播

监听事件

安装并实例化 Laravel Echo,即可开始监听 Laravel 应用程序广播的事件。首先,使用channel方法来获取频道实例,然后调用listen方法来监听指定的事件:

1Echo.channel(`orders.${this.order.id}`)
2 .listen('OrderShipmentStatusUpdated', (e) => {
3 console.log(e.order.name);
4 });

如果您想在私有频道上监听事件,请使用该private方法。您可以继续链接调用该listen方法,以在单个频道上监听多个事件:

1Echo.private(`orders.${this.order.id}`)
2 .listen(/* ... */)
3 .listen(/* ... */)
4 .listen(/* ... */);

停止监听事件

如果您想在不离开频道的情况下停止监听给定事件,您可以使用该stopListening方法:

1Echo.private(`orders.${this.order.id}`)
2 .stopListening('OrderShipmentStatusUpdated');

离开频道

要离开频道,您可以调用leaveChannelEcho 实例上的方法:

1Echo.leaveChannel(`orders.${this.order.id}`);

如果您想离开某个频道及其关联的私人频道和在线频道,您可以调用该leave方法:

1Echo.leave(`orders.${this.order.id}`);

命名空间

你可能已经注意到,在上面的示例中,我们没有App\Events为事件类指定完整的命名空间。这是因为 Echo 会自动假定事件位于该App\Events命名空间中。但是,你可以在实例化 Echo 时通过传递配置选项来配置根命名空间namespace

1window.Echo = new Echo({
2 broadcaster: 'pusher',
3 // ...
4 namespace: 'App.Other.Namespace'
5});

或者,你可以在使用 Echo 订阅事件类时为其添加前缀.。这样你就可以始终指定完全限定的类名:

1Echo.channel('orders')
2 .listen('.Namespace\\Event\\Class', (e) => {
3 // ...
4 });

使用 React 或 Vue

Laravel Echo 包含 React 和 Vue 钩子,可轻松监听事件。首先,调用useEcho用于监听私有事件的钩子。useEcho当使用组件卸载时,钩子将自动退出通道:

1import { useEcho } from "@laravel/echo-react";
2 
3useEcho(
4 `orders.${orderId}`,
5 "OrderShipmentStatusUpdated",
6 (e) => {
7 console.log(e.order);
8 },
9);
1<script setup lang="ts">
2import { useEcho } from "@laravel/echo-vue";
3 
4useEcho(
5 `orders.${orderId}`,
6 "OrderShipmentStatusUpdated",
7 (e) => {
8 console.log(e.order);
9 },
10);
11</script>

您可以通过提供一系列事件来监听多个事件useEcho

1useEcho(
2 `orders.${orderId}`,
3 ["OrderShipmentStatusUpdated", "OrderShipped"],
4 (e) => {
5 console.log(e.order);
6 },
7);

您还可以指定广播事件有效负载数据的形状,以提供更高的类型安全性和编辑便利性:

1type OrderData = {
2 order: {
3 id: number;
4 user: {
5 id: number;
6 name: string;
7 };
8 created_at: string;
9 };
10};
11 
12useEcho<OrderData>(`orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => {
13 console.log(e.order.id);
14 console.log(e.order.user.id);
15});

useEcho当使用组件卸载时,钩子将自动离开通道;但是,您可以利用返回的函数在必要时以编程方式手动停止/开始监听通道

1import { useEcho } from "@laravel/echo-react";
2 
3const { leaveChannel, leave, stopListening, listen } = useEcho(
4 `orders.${orderId}`,
5 "OrderShipmentStatusUpdated",
6 (e) => {
7 console.log(e.order);
8 },
9);
10 
11// Stop listening without leaving channel...
12stopListening();
13 
14// Start listening again...
15listen();
16 
17// Leave channel...
18leaveChannel();
19 
20// Leave a channel and also its associated private and presence channels...
21leave();
1<script setup lang="ts">
2import { useEcho } from "@laravel/echo-vue";
3 
4const { leaveChannel, leave, stopListening, listen } = useEcho(
5 `orders.${orderId}`,
6 "OrderShipmentStatusUpdated",
7 (e) => {
8 console.log(e.order);
9 },
10);
11 
12// Stop listening without leaving channel...
13stopListening();
14 
15// Start listening again...
16listen();
17 
18// Leave channel...
19leaveChannel();
20 
21// Leave a channel and also its associated private and presence channels...
22leave();
23</script>

连接到公共频道

要连接到公共频道,您可以使用useEchoPublic钩子:

1import { useEchoPublic } from "@laravel/echo-react";
2 
3useEchoPublic("posts", "PostPublished", (e) => {
4 console.log(e.post);
5});
1<script setup lang="ts">
2import { useEchoPublic } from "@laravel/echo-vue";
3 
4useEchoPublic("posts", "PostPublished", (e) => {
5 console.log(e.post);
6});
7</script>

连接到 Presence Channels

要连接到存在通道,您可以使用useEchoPresence钩子:

1import { useEchoPresence } from "@laravel/echo-react";
2 
3useEchoPresence("posts", "PostPublished", (e) => {
4 console.log(e.post);
5});
1<script setup lang="ts">
2import { useEchoPresence } from "@laravel/echo-vue";
3 
4useEchoPresence("posts", "PostPublished", (e) => {
5 console.log(e.post);
6});
7</script>

存在通道

在线状态频道在私人频道的安全性基础上,还新增了频道订阅者信息感知功能。这使得构建强大的协作应用功能变得轻而易举,例如当其他用户正在查看同一页面时通知用户,或列出聊天室成员信息。

授权在线状态通道

所有在线状态频道也都是私有频道;因此,用户必须获得授权才能访问它们。但是,在为在线状态频道定义授权回调时,您不会返回true用户是否有权加入频道。相反,您应该返回一个包含用户数据的数组。

授权回调返回的数据将提供给 JavaScript 应用中的在线状态频道事件监听器。如果用户未被授权加入在线状态频道,则应返回falsenull

1use App\Models\User;
2 
3Broadcast::channel('chat.{roomId}', function (User $user, int $roomId) {
4 if ($user->canJoinRoom($roomId)) {
5 return ['id' => $user->id, 'name' => $user->name];
6 }
7});

加入在线状态频道

要加入在线状态频道,您可以使用 Echo 的join方法。该join方法将返回一个PresenceChannel实现,除了公开listen方法之外,它还允许您订阅herejoiningleaving事件。

1Echo.join(`chat.${roomId}`)
2 .here((users) => {
3 // ...
4 })
5 .joining((user) => {
6 console.log(user.name);
7 })
8 .leaving((user) => {
9 console.log(user.name);
10 })
11 .error((error) => {
12 console.error(error);
13 });

here成功加入频道后,回调函数会立即执行,并接收一个数组,其中包含当前订阅该频道的所有其他用户的用户信息。新用户加入频道时会执行该方法joiningleaving用户离开频道时会执行该方法。error当身份验证端点返回除 200 以外的 HTTP 状态码,或者解析返回的 JSON 时出现问题时,也会执行该方法。

向 Presence Channels 进行广播

在线状态频道可以像公共频道或私人频道一样接收事件。以聊天室为例,我们可能希望将NewMessage事件广播到聊天室的在线状态频道。为此,我们将从PresenceChannel事件的broadcastOn方法中返回一个实例:

1/**
2 * Get the channels the event should broadcast on.
3 *
4 * @return array<int, \Illuminate\Broadcasting\Channel>
5 */
6public function broadcastOn(): array
7{
8 return [
9 new PresenceChannel('chat.'.$this->message->room_id),
10 ];
11}

与其他事件一样,您可以使用broadcast帮助程序和toOthers方法来排除当前用户接收广播:

1broadcast(new NewMessage($message));
2 
3broadcast(new NewMessage($message))->toOthers();

与其他类型的事件一样,您可以使用 Echo 的listen方法监听发送到在线状态通道的事件:

1Echo.join(`chat.${roomId}`)
2 .here(/* ... */)
3 .joining(/* ... */)
4 .leaving(/* ... */)
5 .listen('NewMessage', (e) => {
6 // ...
7 });

模特广播

在阅读以下有关模型广播的文档之前,我们建议您熟悉 Laravel 模型广播服务的一般概念以及如何手动创建和监听广播事件。

在应用程序的Eloquent 模型创建、更新或删除时,广播事件是很常见的。当然,这可以通过手动定义 Eloquent 模型状态变化的自定义事件并使用接口标记这些事件来轻松实现ShouldBroadcast

但是,如果您在应用程序中没有将这些事件用于其他目的,那么仅出于广播目的创建事件类可能会很麻烦。为了解决这个问题,Laravel 允许您指示 Eloquent 模型应自动广播其状态变化。

首先,你的 Eloquent 模型应该使用Illuminate\Database\Eloquent\BroadcastsEventstrait。此外,模型应该定义一个broadcastOn方法,该方法将返回一个通道数组,模型的事件应该在这些通道上广播:

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Broadcasting\Channel;
6use Illuminate\Broadcasting\PrivateChannel;
7use Illuminate\Database\Eloquent\BroadcastsEvents;
8use Illuminate\Database\Eloquent\Factories\HasFactory;
9use Illuminate\Database\Eloquent\Model;
10use Illuminate\Database\Eloquent\Relations\BelongsTo;
11 
12class Post extends Model
13{
14 use BroadcastsEvents, HasFactory;
15 
16 /**
17 * Get the user that the post belongs to.
18 */
19 public function user(): BelongsTo
20 {
21 return $this->belongsTo(User::class);
22 }
23 
24 /**
25 * Get the channels that model events should broadcast on.
26 *
27 * @return array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>
28 */
29 public function broadcastOn(string $event): array
30 {
31 return [$this, $this->user];
32 }
33}

一旦您的模型包含此特征并定义其广播渠道,它将在创建、更新、删除、丢弃或恢复模型实例时开始自动广播事件。

此外,您可能注意到该broadcastOn方法接收一个字符串$event参数。此参数包含模型上发生的事件类型,其值为createdupdateddeletedtrashedrestored。通过检查此变量的值,您可以确定模型应该针对特定事件向哪些渠道(如果有)进行广播:

1/**
2 * Get the channels that model events should broadcast on.
3 *
4 * @return array<string, array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>>
5 */
6public function broadcastOn(string $event): array
7{
8 return match ($event) {
9 'deleted' => [],
10 default => [$this, $this->user],
11 };
12}

自定义模型广播事件创建

有时,你可能希望自定义 Laravel 创建底层模型广播事件的方式。你可以newBroadcastableEvent在 Eloquent 模型上定义一个方法来实现。该方法应该返回一个Illuminate\Database\Eloquent\BroadcastableModelEventOccurred实例:

1use Illuminate\Database\Eloquent\BroadcastableModelEventOccurred;
2 
3/**
4 * Create a new broadcastable model event for the model.
5 */
6protected function newBroadcastableEvent(string $event): BroadcastableModelEventOccurred
7{
8 return (new BroadcastableModelEventOccurred(
9 $this, $event
10 ))->dontBroadcastToCurrentUser();
11}

模范广播大会

渠道惯例

您可能已经注意到,broadcastOn上面模型示例中的方法没有返回Channel实例。相反,Eloquent 模型是直接返回的。如果您的模型方法返回了 Eloquent 模型实例broadcastOn(或包含在方法返回的数组中),Laravel 将自动使用模型的类名和主键标识符作为通道名称,为该模型实例化一个私有通道实例。

因此,App\Models\User带有idof的模型1将被转换为Illuminate\Broadcasting\PrivateChannel名称为 的实例App.Models.User.1。当然,除了从模型broadcastOn方法返回 Eloquent 模型实例之外,您还可以返回完整的Channel实例,以便完全控制模型的通道名称:

1use Illuminate\Broadcasting\PrivateChannel;
2 
3/**
4 * Get the channels that model events should broadcast on.
5 *
6 * @return array<int, \Illuminate\Broadcasting\Channel>
7 */
8public function broadcastOn(string $event): array
9{
10 return [
11 new PrivateChannel('user.'.$this->id)
12 ];
13}

如果你计划在模型broadcastOn方法中显式返回一个通道实例,可以将一个 Eloquent 模型实例传递给通道的构造函数。这样做时,Laravel 会使用上面讨论过的模型通道约定将 Eloquent 模型转换为通道名称字符串:

1return [new Channel($this->user)];

如果需要确定模型的通道名称,可以broadcastChannel在任何模型实例上调用该方法。例如,此方法返回带有 的模型App.Models.User.1字符串App\Models\Userid1

1$user->broadcastChannel();

Events公约

由于模型广播事件与应用程序目录中的“实际”事件无关App\Events,因此会根据约定为其分配名称和有效负载。Laravel 的约定是使用模型的类名(不包含命名空间)和触发广播的模型事件名称来广播事件。

因此,例如,模型的更新App\Models\Post将向您的客户端应用程序广播一个事件,PostUpdated如下所示:

1{
2 "model": {
3 "id": 1,
4 "title": "My first post"
5 ...
6 },
7 ...
8 "socket": "someSocketId"
9}

模型的删除App\Models\User将广播一个名为的事件UserDeleted

如果您愿意,可以通过在模型中添加broadcastAsand方法来定义自定义广播名称和负载。这些方法接收正在发生的模型事件/操作的名称,允许您为每个模型操作自定义事件的名称和负载。如果从方法返回,Laravel 将在广播事件时使用上面讨论过的模型广播事件名称约定:broadcastWithnullbroadcastAs

1/**
2 * The model event's broadcast name.
3 */
4public function broadcastAs(string $event): string|null
5{
6 return match ($event) {
7 'created' => 'post.created',
8 default => null,
9 };
10}
11 
12/**
13 * Get the data to broadcast for the model.
14 *
15 * @return array<string, mixed>
16 */
17public function broadcastWith(string $event): array
18{
19 return match ($event) {
20 'created' => ['title' => $this->title],
21 default => ['model' => $this],
22 };
23}

监听模型广播

将特征添加BroadcastsEvents到模型并定义模型broadcastOn方法后,您就可以在客户端应用程序中监听广播的模型事件了。在开始之前,您可以参考关于监听事件的完整文档。

首先,使用该private方法获取一个通道实例,然后调用该listen方法监听指定的事件。通常,传递给该private方法的通道名称应符合 Laravel模型广播约定

获取频道实例后,您可以使用该listen方法监听特定事件。由于模型广播事件与应用程序App\Events目录中的“实际”事件无关,因此事件名称必须以 为前缀,.以表明它不属于特定的命名空间。每个模型广播事件都有一个model属性,该属性包含该模型的所有可广播属性:

1Echo.private(`App.Models.User.${this.user.id}`)
2 .listen('.UserUpdated', (e) => {
3 console.log(e.model);
4 });

使用 React 或 Vue

如果您正在使用 React 或 Vue,您可以使用 Laravel Echo 附带的useEchoModel钩子轻松监听模型广播:

1import { useEchoModel } from "@laravel/echo-react";
2 
3useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => {
4 console.log(e.model);
5});
1<script setup lang="ts">
2import { useEchoModel } from "@laravel/echo-vue";
3 
4useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => {
5 console.log(e.model);
6});
7</script>

您还可以指定模型事件有效负载数据的形状,从而提供更高的类型安全性和编辑便利性:

1type User = {
2 id: number;
3 name: string;
4 email: string;
5};
6 
7useEchoModel<User, "App.Models.User">("App.Models.User", userId, ["UserUpdated"], (e) => {
8 console.log(e.model.id);
9 console.log(e.model.name);
10});

客户Events

使用推送通道时,您必须在应用程序仪表板的“应用程序设置”部分中启用“客户端事件”选项才能发送客户端事件。

有时你可能希望将事件广播给其他已连接的客户端,而无需访问你的 Laravel 应用程序。这对于诸如“输入”通知之类的情况尤其有用,你需要提醒应用程序的用户,有其他用户正在给定屏幕上输入消息。

要广播客户端事件,您可以使用 Echo 的whisper方法:

1Echo.private(`chat.${roomId}`)
2 .whisper('typing', {
3 name: this.user.name
4 });
1import { useEcho } from "@laravel/echo-react";
2 
3const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
4 console.log('Chat event received:', e);
5});
6 
7channel().whisper('typing', { name: user.name });
1<script setup lang="ts">
2import { useEcho } from "@laravel/echo-vue";
3 
4const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
5 console.log('Chat event received:', e);
6});
7 
8channel().whisper('typing', { name: user.name });
9</script>

要监听客户端事件,您可以使用该listenForWhisper方法:

1Echo.private(`chat.${roomId}`)
2 .listenForWhisper('typing', (e) => {
3 console.log(e.name);
4 });
1import { useEcho } from "@laravel/echo-react";
2 
3const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
4 console.log('Chat event received:', e);
5});
6 
7channel().listenForWhisper('typing', (e) => {
8 console.log(e.name);
9});
1<script setup lang="ts">
2import { useEcho } from "@laravel/echo-vue";
3 
4const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
5 console.log('Chat event received:', e);
6});
7 
8channel().listenForWhisper('typing', (e) => {
9 console.log(e.name);
10});
11</script>

通知

通过将事件广播与通知配对,您的 JavaScript 应用程序无需刷新页面即可接收新通知。在开始之前,请务必阅读有关使用广播通知渠道的文档。

配置通知使用广播通道后,您可以使用 Echo 的notification方法监听广播事件。请记住,通道名称应与接收通知的实体的类名匹配:

1Echo.private(`App.Models.User.${userId}`)
2 .notification((notification) => {
3 console.log(notification.type);
4 });
1import { useEchoModel } from "@laravel/echo-react";
2 
3const { channel } = useEchoModel('App.Models.User', userId);
4 
5channel().notification((notification) => {
6 console.log(notification.type);
7});
1<script setup lang="ts">
2import { useEchoModel } from "@laravel/echo-vue";
3 
4const { channel } = useEchoModel('App.Models.User', userId);
5 
6channel().notification((notification) => {
7 console.log(notification.type);
8});
9</script>

App\Models\User在此示例中,所有通过该渠道发送到实例的通知broadcast都将由回调接收。该App.Models.User.{id}渠道的渠道授权回调包含在您的应用程序routes/channels.php文件中。