广播系统
广播系统
介绍
在许多现代 Web 应用中,WebSocket 被用于实现实时、动态更新的用户界面。当服务器上的某些数据发生更新时,一条消息通常会通过 WebSocket 连接发送出去,由客户端进行处理。对于需要在用户界面中反映的数据变化,WebSocket 提供了一种比持续轮询应用服务器更高效的替代方案。
例如,假设你的应用程序能够将用户数据导出为 CSV 文件并通过电子邮件发送给他们。然而,创建这个 CSV 文件需要几分钟时间,因此你选择在 队列任务中创建并发送这个 CSV 文件。当 CSV 文件创建完成并发送给用户后,我们可以使用事件广播来分发一个 App\Events\UserDataExported
事件,该事件会被应用的 JavaScript 接收。一旦接收到该事件,我们就可以向用户显示一条消息,告知他们的 CSV 文件已通过电子邮件发送,而无需他们刷新页面。
为了帮助你构建这类功能,Laravel 让你能够轻松地通过 WebSocket 连接「广播」服务器端的 Laravel 事件。广播 Laravel 事件能让你在服务器端的 Laravel 应用与客户端的 JavaScript 应用之间共享相同的事件名称和数据。
广播的核心概念很简单:客户端在前端连接到命名频道,而你的 Laravel 应用在后端向这些频道广播事件。这些事件可以包含你希望提供给前端的任何额外数据。
支持的驱动
默认情况下,Laravel 包含三种服务器端广播驱动供你选择: Laravel Reverb, Pusher Channels, 和 Ably.
注意
在深入学习事件广播之前,请确保你已阅读 Laravel 关于 事件 和 侦听器的文档。
快速入门
默认情况下,新的 Laravel 应用中未启用广播功能。 你可以使用 install:broadcasting
命令启用广播:
php artisan install:broadcasting
install:broadcasting
命令会提示你选择想要使用的事件广播服务。此外, 它还会创建 config/broadcasting.php
配置文件和 routes/channels.php
文件,你可以在其中注册应用的广播授权路由和回调。
Laravel 提供了几个开箱即用的广播驱动程序: Laravel Reverb, Pusher Channels, Ably, 以及用于本地开发和调试的 log
驱动。此外, 还包含一个 null
驱动, 允许你在测试期间禁用广播。 这些驱动各自的配置示例都包含在 config/broadcasting.php
配置文件中。
应用程序的所有事件广播配置都存储在 config/broadcasting.php
配置文件中。 如果你的应用中不存在该文件,不必担心;运行 install:broadcasting
Artisan 命令时会自动创建它。
后续步骤
启用事件广播后,你就可以进一步学习如何 定义广播事件和监听事件了。 如果你使用的是 Laravel 的 React 或 Vue 入门套件,你就可以通过 Echo 的 useEcho 钩子监听事件。
注意
在广播任何事件之前,你应该先配置并运行队列工作进程. 所有事件广播都是通过任务队列完成的,这样应用程序的响应时间就不会因事件广播而受到严重影响。
服务端安装
要开始使用 Laravel 的事件广播功能,我们需要在 Laravel 应用中进行一些配置,并安装几个包。
事件广播通过服务端广播驱动实现,该驱动会广播你的 Laravel 事件,以便 Laravel Echo(一个 JavaScript 库)能在浏览器客户端中接收这些事件。别担心,我们会逐步介绍安装过程的每个部分。
Reverb
若要使用 Reverb 作为事件广播器并快速启用对 Laravel 广播功能的支持,可以使用 --reverb
选项调用 install:broadcasting
Artisan 命令。该 Artisan 命令会安装 Reverb 所需的 Composer 和 NPM 包,并使用适当的变量更新应用的 .env
文件:
php artisan install:broadcasting --reverb
手动安装
运行 install:broadcasting
命令时,系统会提示你安装 Laravel Reverb。当然,你也可以通过 Composer 包管理器手动安装 Reverb:
composer require laravel/reverb
包安装完成后,你可以运行 Reverb 的安装命令以发布配置文件、添加 Reverb 所需的环境变量,并在应用中启用事件广播:
php artisan reverb:install
你可以在 Reverb 文档中找到详细的安装和使用说明。
Pusher Channels
如果你要使用 Pusher 作为事件广播器并快速启用对 Laravel 广播功能的支持,可以使用 --pusher
选项调用 install:broadcasting
Artisan 命令。 该 Artisan 命令会提示你输入 Pusher 凭证、安装 Pusher PHP 和 JavaScript SDK,并使用适当的变量更新应用的 .env
文件:
php artisan install:broadcasting --pusher
手动安装
如需手动安装 Pusher,可以通过 Composer 包管理器安装 Pusher Channels PHP SDK:
composer require pusher/pusher-php-server
接下来,你需要在 config/broadcasting.php
配置文件中配置 Pusher Channels 凭证。该文件中已包含 Pusher Channels 的配置示例,你可以直接指定 key、secret 和应用 ID。通常,你应该在应用的 .env
文件中配置 Pusher Channels 凭证:
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_APP_KEY="your-pusher-key"
PUSHER_APP_SECRET="your-pusher-secret"
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME="https"
PUSHER_APP_CLUSTER="mt1"
config/broadcasting.php
文件中的 pusher
配置还允许你指定 Channels 所支持的其他 options
,例如集群(cluster)。
然后,在应用程序的 .env
文件中将 BROADCAST_CONNECTION
环境变量设置为 pusher
:
BROADCAST_CONNECTION=pusher
最后,你就可以安装并配置 Laravel Echo,它将在客户端接收广播事件。
Ably
[!注意]
下面的文档讨论了如何在“Pusher 兼容模式”下使用 Ably。
然而,Ably 团队推荐并维护了一个广播器和 Echo 客户端,它能够利用 Ably 提供的独特功能。
关于使用 Ably 官方维护的驱动程序的更多信息,请查阅 Ably 的 Laravel 广播器文档。
要快速启用使用 Ably 作为事件广播器的 Laravel 广播功能,可以运行带有 --ably
选项的 install:broadcasting
Artisan 命令。
此命令会提示你输入 Ably 凭据,安装 Ably 的 PHP 和 JavaScript SDK,并将相应的变量更新到应用程序的 .env
文件中:
php artisan install:broadcasting --ably
在继续之前,你需要在 Ably 应用设置中启用 Pusher 协议支持。
你可以在 Ably 应用设置面板的 “Protocol Adapter Settings” 部分启用此功能。
手动安装
要手动安装 Ably 支持,你需要通过 Composer 包管理器安装 Ably PHP SDK:
composer require ably/ably-php
接下来,你需要在 config/broadcasting.php
配置文件中配置 Ably 凭据。
该文件中已经包含了一个 Ably 配置示例,你只需快速指定你的 key 即可。
通常,这个值应通过 ABLY_KEY
环境变量 来设置
ABLY_KEY=your-ably-key
然后,在应用程序的 .env
文件中将 BROADCAST_CONNECTION
环境变量设置为 ably
:
BROADCAST_CONNECTION=ably
最后,你就可以安装并配置 Laravel Echo,它将在客户端接收广播事件。
客户端安装
Reverb
Laravel Echo 是一个 JavaScript 库,它让你可以轻松地订阅频道并监听由服务端广播驱动器广播的事件。
当通过 install:broadcasting
Artisan 命令安装 Laravel Reverb 时,Reverb 和 Echo 的脚手架及配置会自动注入到你的应用中。
但是,如果你希望手动配置 Laravel Echo,也可以按照下面的说明进行操作。
手动安装
要在应用的前端手动配置 Laravel Echo,首先需要安装 pusher-js
包,因为 Reverb 使用 Pusher 协议来进行 WebSocket 订阅、频道和消息通信:
npm install --save-dev laravel-echo pusher-js
安装 Echo 之后,你就可以在应用的 JavaScript 中创建一个新的 Echo 实例。一个很好的位置是在 Laravel 框架自带的 resources/js/bootstrap.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'],
});
import { configureEcho } from "@laravel/echo-react";
configureEcho({
broadcaster: "reverb",
// key: import.meta.env.VITE_REVERB_APP_KEY,
// wsHost: import.meta.env.VITE_REVERB_HOST,
// wsPort: import.meta.env.VITE_REVERB_PORT,
// wssPort: import.meta.env.VITE_REVERB_PORT,
// forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
// enabledTransports: ['ws', 'wss'],
});
import { configureEcho } from "@laravel/echo-vue";
configureEcho({
broadcaster: "reverb",
// key: import.meta.env.VITE_REVERB_APP_KEY,
// wsHost: import.meta.env.VITE_REVERB_HOST,
// wsPort: import.meta.env.VITE_REVERB_PORT,
// wssPort: import.meta.env.VITE_REVERB_PORT,
// forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
// enabledTransports: ['ws', 'wss'],
});
接下来,你需要编译应用程序的前端资源:
npm run build
[!警告]
Laravel Echo 的reverb
广播器需要 laravel-echo v1.16.0+。
Pusher Channels
Laravel Echo 是一个 JavaScript 库,它让你可以轻松地订阅频道并监听由服务端广播驱动器广播的事件。
当通过 install:broadcasting --pusher
Artisan 命令安装广播支持时,Pusher 和 Echo 的脚手架及配置会自动注入到你的应用中。
但是,如果你希望手动配置 Laravel Echo,也可以按照以下说明进行操作。
手动安装
要在应用的前端手动配置 Laravel Echo,首先需要安装 laravel-echo
和 pusher-js
包,这些包利用 Pusher 协议来进行 WebSocket 订阅、频道和消息通信:
npm install --save-dev laravel-echo pusher-js
安装 Echo 后,你就可以在应用的 resources/js/bootstrap.js
文件中创建一个新的 Echo 实例:
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
});
import { configureEcho } from "@laravel/echo-react";
configureEcho({
broadcaster: "pusher",
// key: import.meta.env.VITE_PUSHER_APP_KEY,
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
// forceTLS: true,
// wsHost: import.meta.env.VITE_PUSHER_HOST,
// wsPort: import.meta.env.VITE_PUSHER_PORT,
// wssPort: import.meta.env.VITE_PUSHER_PORT,
// enabledTransports: ["ws", "wss"],
});
import { configureEcho } from "@laravel/echo-vue";
configureEcho({
broadcaster: "pusher",
// key: import.meta.env.VITE_PUSHER_APP_KEY,
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
// forceTLS: true,
// wsHost: import.meta.env.VITE_PUSHER_HOST,
// wsPort: import.meta.env.VITE_PUSHER_PORT,
// wssPort: import.meta.env.VITE_PUSHER_PORT,
// enabledTransports: ["ws", "wss"],
});
接下来,你需要在应用的 .env
文件中定义 Pusher 的环境变量。如果这些变量在 .env
文件中还不存在,你应该手动添加:
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_APP_KEY="your-pusher-key"
PUSHER_APP_SECRET="your-pusher-secret"
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME="https"
PUSHER_APP_CLUSTER="mt1"
VITE_APP_NAME="${APP_NAME}"
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
在根据应用的需求调整 Echo 配置之后,你可以编译应用的前端资源:
npm run build
[!注意]
若要了解更多关于编译应用 JavaScript 资源的信息,请参阅 Vite 文档。
使用已有的客户端实例
如果你已经有一个预先配置好的 Pusher Channels 客户端实例,并且希望 Echo 使用它,你可以通过 client
配置选项传递给 Echo:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
const options = {
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY
}
window.Echo = new Echo({
...options,
client: new Pusher(options.key, options)
});
Ably
[!注意]
下面的文档介绍了如何在 “Pusher 兼容模式” 下使用 Ably。
不过,Ably 团队推荐并维护了一个广播器和 Echo 客户端,可以充分利用 Ably 提供的独特功能。
要了解更多关于使用 Ably 官方驱动的信息,请参阅 Ably 的 Laravel 广播器文档。
Laravel Echo 是一个 JavaScript 库,它让你可以轻松地订阅频道并监听由服务端广播驱动器发送的事件。
当你通过 install:broadcasting --ably
Artisan 命令安装广播支持时,Ably 和 Echo 的脚手架与配置会自动注入到你的应用中。
但是,如果你希望手动配置 Laravel Echo,也可以按照以下说明进行操作。
手动安装
要在应用的前端手动配置 Laravel Echo,首先需要安装 laravel-echo
和 pusher-js
这两个包,它们使用 Pusher 协议 来进行 WebSocket 订阅、频道和消息通信:
npm install --save-dev laravel-echo pusher-js
在继续之前,你需要在 Ably 应用设置中启用 Pusher 协议支持。
你可以在 Ably 应用控制台的 Protocol Adapter Settings(协议适配器设置) 中启用此功能。
安装 Echo 之后,就可以在应用的 resources/js/bootstrap.js
文件中创建一个新的 Echo 实例:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
wsHost: 'realtime-pusher.ably.io',
wsPort: 443,
disableStats: true,
encrypted: true,
});
如果你在使用 React,可以这样配置:
import { configureEcho } from "@laravel/echo-react";
configureEcho({
broadcaster: "ably",
// key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
// wsHost: "realtime-pusher.ably.io",
// wsPort: 443,
// disableStats: true,
// encrypted: true,
});
如果你在使用 Vue,可以这样配置:
import { configureEcho } from "@laravel/echo-vue";
configureEcho({
broadcaster: "ably",
// key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
// wsHost: "realtime-pusher.ably.io",
// wsPort: 443,
// disableStats: true,
// encrypted: true,
});
你可能已经注意到,我们在 Ably Echo 配置中引用了一个 VITE_ABLY_PUBLIC_KEY
环境变量。
这个变量的值应该是你 Ably 的 public key(公钥)。
你的公钥就是 Ably Key 中冒号 :
前面的部分。
当你根据需求调整好 Echo 配置后,就可以编译应用的前端资源了:
npm run dev
[!注意]
要了解更多关于编译应用的 JavaScript 资源的信息,请查阅 Vite 文档。
概念概览
Laravel 的事件广播允许你使用基于驱动的方法,通过 WebSockets 将服务端的 Laravel 事件广播到客户端的 JavaScript 应用。
目前,Laravel 附带了 Laravel Reverb、Pusher Channels 和 Ably 驱动。
这些事件可以通过客户端的 Laravel Echo JavaScript 包轻松消费。
事件是通过“频道”广播的,这些频道可以被指定为公共或私有。
任何访问你应用的访客都可以在没有任何认证或授权的情况下订阅一个公共频道;
然而,为了订阅一个私有频道,用户必须被认证并被授权去监听该频道。
使用一个示例应用
在深入研究事件广播的每个组件之前,让我们通过一个电商商店的例子来进行一个高层次的概览。
在我们的应用中,假设我们有一个页面,允许用户查看他们订单的发货状态。
我们还假设当一个发货状态更新被应用处理时,会触发一个 OrderShipmentStatusUpdated
事件:
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
ShouldBroadcast
接口
当用户正在查看他们的某个订单时,我们不希望他们必须刷新页面才能看到状态更新。
相反,我们希望在更新被创建时,就将它们广播到应用中。
因此,我们需要用 ShouldBroadcast
接口来标记 OrderShipmentStatusUpdated
事件。
这会指示 Laravel 在事件被触发时广播它:
<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
class OrderShipmentStatusUpdated implements ShouldBroadcast
{
/**
* 订单实例。
*
* @var \App\Models\Order
*/
public $order;
}
ShouldBroadcast
接口要求我们的事件定义一个 broadcastOn
方法。
这个方法负责返回事件应该广播到的频道。
在生成的事件类中,这个方法的空壳(stub)已经定义好了,所以我们只需要补充其细节。
我们只希望订单的创建者能够看到状态更新,因此我们会将事件广播到一个与该订单绑定的私有频道:
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
/**
* 获取事件应该广播到的频道
*/
public function broadcastOn(): Channel
{
return new PrivateChannel('orders.'.$this->order->id);
}
如果你希望事件广播到多个频道,你可以返回一个 array
来代替:
use Illuminate\Broadcasting\PrivateChannel;
/**
* 获取事件应该广播到的频道们
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('orders.'.$this->order->id),
// ...
];
}
授权频道
请记住,用户必须被授权才能监听私有频道。
我们可以在应用的 routes/channels.php
文件中定义频道的授权规则。
在这个示例中,我们需要验证任何尝试监听私有 orders.1
频道的用户,实际上是否是该订单的创建者:
use App\Models\Order;
use App\Models\User;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
channel
方法接受两个参数:频道的名称,以及一个回调函数,该函数返回 true
或 false
,指示用户是否被授权监听该频道。
所有授权回调函数的第一个参数都会接收到当前认证的用户,后续参数则会接收到任何通配符参数。
在这个示例中,我们使用 {orderId}
占位符,表示频道名称中的 “ID” 部分是一个通配符。
监听事件广播
接下来,只需在我们的 JavaScript 应用中监听事件即可。
我们可以使用 Laravel Echo 来实现。
Laravel Echo 内置的 React 和 Vue Hook 让入门变得简单,并且默认情况下,事件的所有公共属性都会包含在广播事件中:
import { useEcho } from "@laravel/echo-react";
useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
</script>
定义广播事件
为了通知 Laravel 某个事件应该被广播,你必须在事件类上实现 Illuminate\Contracts\Broadcasting\ShouldBroadcast
接口。
该接口已被框架生成的所有事件类导入,所以你可以轻松地将其添加到你的任意事件中。
ShouldBroadcast
接口要求你实现一个方法:broadcastOn
。
broadcastOn
方法应该返回一个频道或者频道数组,这些事件将被广播到这些频道。
频道应当是 Channel
、PrivateChannel
或 PresenceChannel
的实例。
Channel
实例表示公共频道,任何用户都可以订阅。PrivateChannel
和PresenceChannel
表示私有频道,需要进行频道授权。
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
class ServerCreated implements ShouldBroadcast
{
use SerializesModels;
/**
* 创建一个新的事件实例。
*/
public function __construct(
public User $user,
) {}
/**
* 获取事件应该广播到的频道。
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('user.'.$this->user->id),
];
}
}
在实现 ShouldBroadcast
接口之后,你只需要像平常一样触发事件 即可。
一旦事件被触发,队列任务 将会自动使用你指定的广播驱动来广播该事件。
广播名称
默认情况下,Laravel 会使用事件类名来广播事件。
但是,你可以通过在事件中定义 broadcastAs
方法来自定义广播名称:
/**
* 事件的广播名称
*/
public function broadcastAs(): string
{
return 'server.created';
}
如果你使用 broadcastAs
方法自定义了广播名称,你应该确保在注册监听器时在事件名前加一个 .
字符。
这会指示 Echo 不要在事件前加上应用的命名空间:
.listen('.server.created', function (e) {
// ...
});
广播数据
当事件被广播时,它的所有 public
属性会自动被序列化,并作为事件的 payload 广播,这样你就可以在 JavaScript 应用中访问它的任意公共数据。
例如,如果你的事件只有一个 public 属性 $user
,它包含一个 Eloquent 模型,那么事件的广播 payload 会是:
{
"user": {
"id": 1,
"name": "Patrick Stewart"
...
}
}
然而,如果你希望对广播 payload 有更细粒度的控制,你可以在事件中添加一个 broadcastWith
方法。
该方法应该返回你希望广播的 payload 数据数组:
/**
* 获取要广播的数据。
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
return ['id' => $this->user->id];
}
广播队列
默认情况下,每个广播事件都会被放入 queue.php
配置文件中指定的默认队列连接的默认队列中。
你可以通过在事件类中定义 connection
和 queue
属性,自定义广播器使用的队列连接和队列名称:
/**
* 广播事件时要使用的队列连接名称。
*
* @var string
*/
public $connection = 'redis';
/**
* 放置广播任务的队列名称。
*
* @var string
*/
public $queue = 'default';
或者,你也可以通过在事件中定义一个 broadcastQueue
方法来自定义队列名称:
/**
* 放置广播任务的队列名称。
*/
public function broadcastQueue(): string
{
return 'default';
}
如果你希望使用 sync
队列而不是默认队列驱动来广播事件,你可以实现 ShouldBroadcastNow
接口,而不是 ShouldBroadcast
:
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class OrderShipmentStatusUpdated implements ShouldBroadcastNow
{
// ...
}
广播条件
有时候,你希望只有在某个条件为真时才广播事件。
你可以通过在事件类中添加 broadcastWhen
方法来定义这些条件:
/**
* 判断该事件是否应该广播
*/
public function broadcastWhen(): bool
{
return $this->order->value > 100;
}
广播与数据库事务
当广播事件在数据库事务中被派发时,它们可能会在数据库事务提交之前就被队列处理。
当发生这种情况时,在事务中对模型或数据库记录所做的任何更新可能还未反映到数据库中。
此外,在事务中创建的任何模型或数据库记录可能在数据库中还不存在。
如果你的事件依赖这些模型,当处理广播事件的队列任务时可能会发生意外错误。
如果你的队列连接的 after_commit
配置选项设置为 false
,你仍然可以通过在事件类上实现 ShouldDispatchAfterCommit
接口来指示特定的广播事件应在所有未提交的数据库事务提交后再派发:
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Queue\SerializesModels;
class ServerCreated implements ShouldBroadcast, ShouldDispatchAfterCommit
{
use SerializesModels;
}
[!注意]
若要了解更多关于解决这些问题的信息,请查阅 队列任务与数据库事务 文档。
授权频道
私有频道要求你授权当前认证的用户是否可以真正监听该频道。
这是通过向你的 Laravel 应用发送一个 HTTP 请求,带上频道名称,并让应用决定用户是否可以监听该频道来实现的。
当使用 Laravel Echo 时,授权订阅私有频道的 HTTP 请求会自动发出。
当广播功能启用时,Laravel 会自动注册 /broadcasting/auth
路由来处理授权请求。
/broadcasting/auth
路由会自动放置在 web
中间件组中。
定义授权回调
接下来,我们需要定义逻辑来实际判断当前认证用户是否可以监听给定的频道。
这在由 install:broadcasting
Artisan 命令创建的 routes/channels.php
文件中完成。
在此文件中,你可以使用 Broadcast::channel
方法来注册频道授权回调:
use App\Models\User;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
channel
方法接受两个参数:频道的名称,以及一个回调函数,该回调返回 true
或 false
,用于指示用户是否被授权监听该频道。
所有授权回调的第一个参数会接收当前认证的用户,后续参数会接收任何通配符参数。
在此示例中,我们使用 {orderId}
占位符,表示频道名称中的 “ID” 部分是一个通配符。
你可以使用 channel:list
Artisan 命令查看应用的广播授权回调列表:
php artisan channel:list
授权回调模型绑定
就像 HTTP 路由一样,频道路由也可以利用隐式和显式的路由模型绑定。
例如,你可以不再接收字符串或数字类型的订单 ID,而是直接请求一个 Order
模型实例:
use App\Models\Order;
use App\Models\User;
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
return $user->id === $order->user_id;
});
[!警告]
与 HTTP 路由模型绑定不同,频道模型绑定不支持自动的隐式模型绑定作用域。
不过这通常不是问题,因为大多数频道可以基于单个模型的唯一主键进行作用域限制。
授权回调认证
私有和存在广播频道会通过应用的默认认证守卫(authentication guard)对当前用户进行认证。
如果用户未认证,频道授权会被自动拒绝,授权回调不会被执行。
然而,如果需要,你可以为传入请求指定多个自定义守卫:
Broadcast::channel('channel', function () {
// ...
}, ['guards' => ['web', 'admin']]);
定义频道类
如果你的应用使用很多不同的频道,routes/channels.php
文件可能会变得很臃肿。
因此,你可以不用闭包来授权频道,而是使用 频道类。
要生成一个频道类,请使用 make:channel
Artisan 命令。
此命令会在 App/Broadcasting
目录下创建一个新的频道类:
php artisan make:channel OrderChannel
接下来,在你的 routes/channels.php
文件中注册你的频道:
use App\Broadcasting\OrderChannel;
Broadcast::channel('orders.{order}', OrderChannel::class);
最后,你可以将频道的授权逻辑放在频道类的 join
方法中。
这个 join
方法将包含你通常会放在频道授权闭包中的相同逻辑。
你也可以利用频道模型绑定:
<?php
namespace App\Broadcasting;
use App\Models\Order;
use App\Models\User;
class OrderChannel
{
/**
* 创建一个新的频道实例。
*/
public function __construct() {}
/**
* 验证用户对频道的访问权限。
*/
public function join(User $user, Order $order): array|bool
{
return $user->id === $order->user_id;
}
}
[!注意]
与 Laravel 中的许多其他类一样,频道类会自动由服务容器解析。
因此,你可以在频道的构造函数中类型提示任何所需的依赖。
广播事件
一旦你定义了一个事件并用 ShouldBroadcast
接口标记它,你只需要使用事件的 dispatch 方法触发该事件即可。
事件分发器会注意到事件被标记为 ShouldBroadcast
接口,并会将事件加入队列以进行广播:
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
仅广播给其他人
在构建使用事件广播的应用时,你可能有时需要将事件广播给某个频道的所有订阅者,但排除当前用户。
你可以使用 broadcast
助手函数和 toOthers
方法来实现:
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->toOthers();
为了更好地理解何时可能需要使用 toOthers
方法,我们来设想一个任务列表应用,其中用户可以通过输入任务名称来创建新任务。
要创建任务,你的应用可能会向 /task
URL 发起请求,该请求会广播任务的创建,并返回新任务的 JSON 表示。
当你的 JavaScript 应用收到该端点的响应时,它可能会直接将新任务插入到任务列表中,如下所示:
axios.post('/task', task)
.then((response) => {
this.tasks.push(response.data);
});
然而,请记住,我们也会广播任务的创建。
如果你的 JavaScript 应用也在监听这个事件以将任务添加到任务列表中,你的列表中就会出现重复任务:
一个来自端点响应,一个来自广播。
你可以通过使用 toOthers
方法来解决这个问题,该方法指示广播器不要将事件广播给当前用户。
[!警告]
你的事件必须使用Illuminate\Broadcasting\InteractsWithSockets
trait,才能调用toOthers
方法。
配置
当你初始化一个 Laravel Echo 实例时,会为该连接分配一个 socket ID。
如果你在 JavaScript 应用中使用全局 Axios 实例来发起 HTTP 请求,该 socket ID 会自动作为 X-Socket-ID
请求头附加到每个外发请求中。
然后,当你调用 toOthers
方法时,Laravel 会从请求头中提取 socket ID,并指示广播器不要向任何拥有该 socket ID 的连接广播事件。
如果你没有使用全局 Axios 实例,你需要手动配置你的 JavaScript 应用,以便在所有外发请求中发送 X-Socket-ID
请求头。
你可以使用 Echo.socketId
方法获取 socket ID:
var socketId = Echo.socketId();
自定义连接
如果你的应用与多个广播连接交互,并且希望使用默认广播器以外的广播器来广播事件,你可以使用 via
方法指定将事件推送到哪个连接:
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->via('pusher');
或者,你也可以在事件的构造函数中调用 broadcastVia
方法来指定事件的广播连接。
但是,在这样做之前,你应该确保事件类使用了 InteractsWithBroadcasting
trait:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithBroadcasting;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
class OrderShipmentStatusUpdated implements ShouldBroadcast
{
use InteractsWithBroadcasting;
/**
* 创建一个新的事件实例
*/
public function __construct()
{
$this->broadcastVia('pusher');
}
}
匿名事件
有时,你可能希望向应用前端广播一个简单事件,而不创建专门的事件类。
为此,Broadcast
facade 允许你广播“匿名事件”:
Broadcast::on('orders.'.$order->id)->send();
上面的示例将广播如下事件:
{
"event": "AnonymousEvent",
"data": "[]",
"channel": "orders.1"
}
使用 as
和 with
方法,你可以自定义事件的名称和数据:
Broadcast::on('orders.'.$order->id)
->as('OrderPlaced')
->with($order)
->send();
上面的示例将广播一个类似如下的事件:
{
"event": "OrderPlaced",
"data": "{ id: 1, total: 100 }",
"channel": "orders.1"
}
如果你希望在私有或存在频道上广播匿名事件,你可以使用 private
和 presence
方法:
Broadcast::private('orders.'.$order->id)->send();
Broadcast::presence('channels.'.$channel->id)->send();
使用 send
方法广播匿名事件会将事件派发到应用的队列进行处理。
但是,如果你希望立即广播事件,可以使用 sendNow
方法:
Broadcast::on('orders.'.$order->id)->sendNow();
如果你希望将事件广播给频道的所有订阅者,但排除当前认证用户,可以调用 toOthers
方法:
Broadcast::on('orders.'.$order->id)
->toOthers()
->send();
接收广播
监听事件
一旦你安装并实例化了 Laravel Echo,就可以开始监听从 Laravel 应用广播的事件了。
首先,使用 channel
方法获取一个频道实例,然后调用 listen
方法监听指定事件:
Echo.channel(`orders.${this.order.id}`)
.listen('OrderShipmentStatusUpdated', (e) => {
console.log(e.order.name);
});
如果你希望监听私有频道的事件,请使用 private
方法。
你也可以继续链式调用 listen
方法,在单个频道上监听多个事件:
Echo.private(`orders.${this.order.id}`)
.listen(/* ... */)
.listen(/* ... */)
.listen(/* ... */);
停止监听事件
如果你希望停止监听某个事件,但不想离开频道,可以使用 stopListening
方法:
Echo.private(`orders.${this.order.id}`)
.stopListening('OrderShipmentStatusUpdated');
离开频道
要离开一个频道,你可以在 Echo 实例上调用 leaveChannel
方法:
Echo.leaveChannel(`orders.${this.order.id}`);
如果你希望离开一个频道以及它关联的私有和存在频道,可以调用 leave
方法:
Echo.leave(`orders.${this.order.id}`);
命名空间
你可能注意到在上面的示例中,我们没有为事件类指定完整的 App\Events
命名空间。
这是因为 Echo 会自动假设事件位于 App\Events
命名空间中。
然而,你可以在实例化 Echo 时,通过传入 namespace
配置选项来自定义根命名空间:
window.Echo = new Echo({
broadcaster: 'pusher',
// ...
namespace: 'App.Other.Namespace'
});
或者,在使用 Echo 订阅事件时,你可以在事件类前加 .
前缀。
这将允许你始终指定事件类的完整限定名称:
Echo.channel('orders')
.listen('.Namespace\\Event\\Class', (e) => {
// ...
});
在 React 或 Vue 中使用
Laravel Echo 包含 React 和 Vue 钩子,使得监听事件变得非常简单。
要开始使用,请调用 useEcho
钩子,它用于监听私有事件。
当使用组件卸载时,useEcho
钩子会自动离开频道:
import { useEcho } from "@laravel/echo-react";
useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
</script>
你可以通过向 useEcho
提供一个事件数组来监听多个事件:
useEcho(
`orders.${orderId}`,
["OrderShipmentStatusUpdated", "OrderShipped"],
(e) => {
console.log(e.order);
},
);
你还可以指定广播事件的 payload 数据类型,这样可以提供更好的类型安全和编辑便利性:
type OrderData = {
order: {
id: number;
user: {
id: number;
name: string;
};
created_at: string;
};
};
useEcho<OrderData>(`orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => {
console.log(e.order.id);
console.log(e.order.user.id);
});
useEcho
钩子会在消费组件卸载时自动离开频道;
但是,你也可以利用返回的函数在必要时手动停止或重新开始监听频道:
import { useEcho } from "@laravel/echo-react";
const { leaveChannel, leave, stopListening, listen } = useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
// 停止监听,但不离开频道...
stopListening();
// 重新开始监听...
listen();
// 离开频道...
leaveChannel();
// 离开频道,同时离开其关联的私有和存在频道...
leave();
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
const { leaveChannel, leave, stopListening, listen } = useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
// 停止监听,但不离开频道...
stopListening();
// 重新开始监听...
listen();
// 离开频道...
leaveChannel();
// 离开频道,同时离开其关联的私有和存在频道...
leave();
</script>
连接到公共频道
要连接到公共频道,你可以使用 useEchoPublic
钩子:
import { useEchoPublic } from "@laravel/echo-react";
useEchoPublic("posts", "PostPublished", (e) => {
console.log(e.post);
});
<script setup lang="ts">
import { useEchoPublic } from "@laravel/echo-vue";
useEchoPublic("posts", "PostPublished", (e) => {
console.log(e.post);
});
</script>
连接到 Presence 频道
要连接到 presence 频道,你可以使用 useEchoPresence
hook:
import { useEchoPresence } from "@laravel/echo-react";
useEchoPresence("posts", "PostPublished", (e) => {
console.log(e.post);
});
<script setup lang="ts">
import { useEchoPresence } from "@laravel/echo-vue";
useEchoPresence("posts", "PostPublished", (e) => {
console.log(e.post);
});
</script>
Presence 频道
Presence 频道在私有频道安全性的基础上,增加了一个额外功能:能感知谁订阅了这个频道。
这让你很容易构建强大的协作应用功能,比如:当其他用户正在查看同一个页面时通知用户,或者列出聊天室中的所有成员。
Presence 频道授权
所有 presence 频道同时也是私有频道;因此,用户必须被授权访问它们。
不过,在为 presence 频道定义授权回调时,你不会仅仅返回 true
来表示用户被授权加入频道。
相反,你应该返回一个关于该用户的数据数组。
授权回调返回的数据会在 JavaScript 应用中的 presence 频道事件监听器里可用。
如果用户未被授权加入 presence 频道,你应该返回 false
或 null
:
use App\Models\User;
Broadcast::channel('chat.{roomId}', function (User $user, int $roomId) {
if ($user->canJoinRoom($roomId)) {
return ['id' => $user->id, 'name' => $user->name];
}
});
加入 Presence 频道
要加入 presence 频道,你可以使用 Echo 的 join
方法。
join
方法会返回一个 PresenceChannel
实例,它除了暴露 listen
方法外,还允许你订阅 here
、joining
和 leaving
事件。
Echo.join(`chat.${roomId}`)
.here((users) => {
// ...
})
.joining((user) => {
console.log(user.name);
})
.leaving((user) => {
console.log(user.name);
})
.error((error) => {
console.error(error);
});
here
回调会在频道成功加入后立即执行,并会接收到一个数组,该数组包含了当前已订阅该频道的所有其他用户的信息。
当有新用户加入频道时,joining
方法会被执行;当有用户离开频道时,leaving
方法会被执行。
当认证端点返回的 HTTP 状态码不是 200,或者返回的 JSON 解析出错时,error
方法会被执行。
向 Presence 频道广播
Presence 频道和公共频道、私有频道一样,也可以接收事件。
以聊天室为例,我们可能希望向房间的 presence 频道广播 NewMessage
事件。要做到这一点,我们需要在事件的 broadcastOn
方法中返回一个 PresenceChannel
实例:
/**
* 获取事件应广播到的频道。
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PresenceChannel('chat.'.$this->message->room_id),
];
}
和其他事件一样,你可以使用 broadcast
辅助函数和 toOthers
方法来将当前用户排除在接收广播之外:
broadcast(new NewMessage($message));
broadcast(new NewMessage($message))->toOthers();
和其他类型的事件一样,你可以使用 Echo 的 listen
方法来监听发送到 presence 频道的事件:
Echo.join(`chat.${roomId}`)
.here(/* ... */)
.joining(/* ... */)
.leaving(/* ... */)
.listen('NewMessage', (e) => {
// ...
});
模型广播
[!警告]
在阅读下面关于模型广播的文档之前,我们建议你先熟悉 Laravel 的模型广播服务的一般概念,以及如何手动创建和监听广播事件。
在你的应用中,当 Eloquent 模型 被创建、更新或删除时,广播事件是很常见的。
当然,你可以通过手动 为 Eloquent 模型的状态变化定义自定义事件,并让这些事件实现 ShouldBroadcast
接口,轻松实现这一点。
但是,如果你在应用中并不会将这些事件用于其他用途,仅仅为了广播去创建事件类就显得很繁琐。
为了解决这个问题,Laravel 允许你直接声明一个 Eloquent 模型在状态变化时自动广播。
要开始使用,你的 Eloquent 模型需要引入 Illuminate\Database\Eloquent\BroadcastsEvents
trait。
此外,该模型还需要定义一个 broadcastOn
方法,用来返回一个数组,表示模型事件应该广播到的频道:
<?php
namespace App\Models;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Database\Eloquent\BroadcastsEvents;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model
{
use BroadcastsEvents, HasFactory;
/**
* 获取该文章所属的用户。
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* 获取模型事件应广播到的频道。
*
* @return array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>
*/
public function broadcastOn(string $event): array
{
return [$this, $this->user];
}
}
一旦模型引入了这个 trait 并定义了广播频道,它就会在 创建、更新、删除、软删除 (trashed)、恢复 (restored) 时自动广播事件。
另外,你可能注意到 broadcastOn
方法接收了一个字符串 $event
参数。
这个参数表示模型上发生的事件类型,它的值可能是 created
、updated
、deleted
、trashed
或 restored
。
通过检查这个变量的值,你可以决定模型在某个特定事件中应该广播到哪些频道(如果需要的话):
/**
* 获取模型事件应广播到的频道。
*
* @return array<string, array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>>
*/
public function broadcastOn(string $event): array
{
return match ($event) {
'deleted' => [],
default => [$this, $this->user],
};
}
自定义模型广播事件的创建
有时,你可能希望自定义 Laravel 如何创建底层的模型广播事件。
你可以在 Eloquent 模型上定义一个 newBroadcastableEvent
方法来实现这一点。
该方法应返回一个 Illuminate\Database\Eloquent\BroadcastableModelEventOccurred
实例:
use Illuminate\Database\Eloquent\BroadcastableModelEventOccurred;
/**
* 为模型创建一个新的可广播事件。
*/
protected function newBroadcastableEvent(string $event): BroadcastableModelEventOccurred
{
return (new BroadcastableModelEventOccurred(
$this, $event
))->dontBroadcastToCurrentUser();
}
模型广播约定
频道约定
你可能已经注意到,上面示例中的 broadcastOn
方法并没有返回 Channel
实例。
相反,它直接返回了 Eloquent 模型。
如果你的模型的 broadcastOn
方法返回了一个 Eloquent 模型实例(或返回的数组中包含模型实例),Laravel 会自动为该模型实例创建一个私有频道实例。频道名称由模型的类名和主键 ID 组成。
例如,一个 App\Models\User
模型,id
为 1
,将会被转换为一个 Illuminate\Broadcasting\PrivateChannel
实例,频道名为:App.Models.User.1
。
当然,除了从 broadcastOn
方法返回 Eloquent 模型实例外,你也可以直接返回完整的 Channel
实例,以便完全控制模型的频道名称:
use Illuminate\Broadcasting\PrivateChannel;
/**
* 获取模型事件应广播到的频道。
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(string $event): array
{
return [
new PrivateChannel('user.'.$this->id)
];
}
如果你打算从模型的 broadcastOn
方法中显式返回一个频道实例,你可以将一个 Eloquent 模型实例传入频道的构造函数。
这样做时,Laravel 会使用前面提到的模型频道约定,将 Eloquent 模型转换为一个频道名称字符串:
return [new Channel($this->user)];
如果你需要确定一个模型的频道名称,可以在任何模型实例上调用 broadcastChannel
方法。
例如,对于一个 id
为 1
的 App\Models\User
模型,这个方法会返回字符串 App.Models.User.1
:
$user->broadcastChannel();
事件约定
由于模型广播事件并没有关联到你应用的 App\Events
目录下的“实际”事件,它们的名称和负载是基于约定生成的。
Laravel 的约定是:使用模型的类名(不包含命名空间)和触发广播的模型事件名称来广播事件。
例如,对 App\Models\Post
模型的更新操作,会向客户端应用广播一个名为 PostUpdated
的事件,其负载如下:
{
"model": {
"id": 1,
"title": "My first post"
...
},
...
"socket": "someSocketId"
}
删除 App\Models\User
模型时,会广播一个名为 UserDeleted
的事件。
如果你希望自定义广播事件的名称和负载,可以在模型中添加 broadcastAs
和 broadcastWith
方法。
这两个方法会接收当前发生的模型事件 / 操作的名称,从而允许你为每个模型操作自定义事件名称和负载。
如果 broadcastAs
方法返回 null
,Laravel 将在广播事件时使用上面提到的模型广播事件名称约定:
/**
* 模型事件的广播名称。
*/
public function broadcastAs(string $event): string|null
{
return match ($event) {
'created' => 'post.created',
default => null,
};
}
/**
* 获取模型广播的数据。
*
* @return array<string, mixed>
*/
public function broadcastWith(string $event): array
{
return match ($event) {
'created' => ['title' => $this->title],
default => ['model' => $this],
};
}
监听模型广播
一旦你在模型中添加了 BroadcastsEvents
trait 并定义了模型的 broadcastOn
方法,你就可以在客户端应用中开始监听模型广播事件了。
在开始之前,你可能希望先查看完整的 事件监听 文档。
首先,使用 private
方法获取一个频道实例,然后调用 listen
方法来监听指定的事件。
通常,传给 private
方法的频道名称应遵循 Laravel 的 模型广播约定。
获得频道实例后,你可以使用 listen
方法监听某个特定事件。
由于模型广播事件并没有关联到你应用的 App\Events
目录下的“实际”事件,事件名称必须以 .
前缀开头,以表明它不属于某个特定命名空间。
每个模型广播事件都有一个 model
属性,包含了该模型的所有可广播属性:
Echo.private(`App.Models.User.${this.user.id}`)
.listen('.UserUpdated', (e) => {
console.log(e.model);
});
在 React 或 Vue 中使用
如果你使用 React 或 Vue,可以使用 Laravel Echo 提供的 useEchoModel
hook 来轻松监听模型广播:
import { useEchoModel } from "@laravel/echo-react";
useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => {
console.log(e.model);
});
<script setup lang="ts">
import { useEchoModel } from "@laravel/echo-vue";
useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => {
console.log(e.model);
});
</script>
你还可以指定模型事件负载的数据类型,这样可以提供更好的类型安全性和编辑便利性:
type User = {
id: number;
name: string;
email: string;
};
useEchoModel<User, "App.Models.User">("App.Models.User", userId, ["UserUpdated"], (e) => {
console.log(e.model.id);
console.log(e.model.name);
});
客户端事件
[!注意]
如果使用 Pusher Channels,你必须在 应用仪表盘的“应用设置”中启用 Client Events 选项,才能发送客户端事件。
有时,你可能希望广播事件给其他已连接的客户端,而无需通过 Laravel 后端。
这在像“正在输入”通知这种场景下尤其有用,你希望告知其他用户有人正在当前屏幕输入消息。
要广播客户端事件,可以使用 Echo 的 whisper
方法:
Echo.private(`chat.${roomId}`)
.whisper('typing', {
name: this.user.name
});
import { useEcho } from "@laravel/echo-react";
const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
console.log('Chat event received:', e);
});
channel().whisper('typing', { name: user.name });
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
console.log('Chat event received:', e);
});
channel().whisper('typing', { name: user.name });
</script>
要监听客户端事件,可以使用 listenForWhisper
方法:
Echo.private(`chat.${roomId}`)
.listenForWhisper('typing', (e) => {
console.log(e.name);
});
import { useEcho } from "@laravel/echo-react";
const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
console.log('Chat event received:', e);
});
channel().listenForWhisper('typing', (e) => {
console.log(e.name);
});
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
console.log('Chat event received:', e);
});
channel().listenForWhisper('typing', (e) => {
console.log(e.name);
});
</script>
通知
通过将事件广播与 通知 配合使用,你的 JavaScript 应用可以在通知发生时实时接收,而无需刷新页面。
在开始之前,请确保阅读了关于使用 广播通知频道 的文档。
一旦你配置了通知使用广播频道,就可以使用 Echo 的 notification
方法来监听广播事件。
记住,频道名称应与接收通知的实体类名一致:
Echo.private(`App.Models.User.${userId}`)
.notification((notification) => {
console.log(notification.type);
});
import { useEchoModel } from "@laravel/echo-react";
const { channel } = useEchoModel('App.Models.User', userId);
channel().notification((notification) => {
console.log(notification.type);
});
<script setup lang="ts">
import { useEchoModel } from "@laravel/echo-vue";
const { channel } = useEchoModel('App.Models.User', userId);
channel().notification((notification) => {
console.log(notification.type);
});
</script>
在此示例中,所有通过 broadcast
频道发送到 App\Models\User
实例的通知都会被回调接收。
你应用的 routes/channels.php
文件中包含了 App.Models.User.{id}
频道的授权回调。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: