在许多现代 Web 应用程序中,WebSockets 用于实现实时、动态更新的用户界面。当服务器上的一些数据更新时,通常会通过 WebSocket 连接发送一条消息,由客户端处理。WebSockets 提供了一种更高效的替代方案,取代了持续轮询你的应用程序服务器以获取应在你的 UI 中反映的数据变更。
例如,想象一下您的应用程序能够将用户数据导出到 CSV 文件并通过电子邮件发送给他们。然而,创建此 CSV 文件需要几分钟,因此您选择在队列作业中创建并邮寄 CSV。当 CSV 文件创建并邮寄给用户后,我们可以使用事件广播来分派一个 App\Events\UserDataExported 事件,该事件由我们应用程序的 JavaScript 接收。一旦事件被接收,我们就可以向用户显示一条消息,告知他们 CSV 文件已通过电子邮件发送给他们,而无需他们刷新页面。
为协助您构建此类功能,Laravel 使您能够轻松地“广播”您的服务端 Laravel 事件通过 WebSocket 连接。广播您的 Laravel 事件使您能够共享相同的事件名称和数据在您的服务端 Laravel 应用程序和您的客户端 JavaScript 应用程序之间。
广播背后的核心概念很简单:客户端连接到前端的命名通道,而你的 Laravel 应用程序则在后端向这些通道广播事件。这些事件可以包含你希望提供给前端的任何额外数据。
默认情况下,Laravel 包含了三个服务器端广播驱动供你选择: Laravel Reverb, Pusher Channels, and Ably。
[!NOTE]
在深入了解事件广播之前,请确保您已阅读 Laravel 关于 事件和监听器 的文档。
默认情况下,广播在新的 Laravel 应用中未启用。你可以使用 install:broadcasting Artisan 命令启用广播:
php artisan install:broadcastinginstall: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 作为事件广播器时快速启用对 Laravel 广播功能的支持,请调用 install:broadcasting Artisan 命令并附带 --reverb 选项。此 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 文档 中找到详细的 Reverb 安装和使用说明。
为了快速启用对 Laravel 广播功能的支持,同时使用 Pusher 作为你的事件广播器,调用 install:broadcasting Artisan 命令并附带 --pusher 选项。 这个 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 配置示例,您可以快速指定您的键、密钥和应用程序 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,例如集群。
然后,将 BROADCAST_CONNECTION 环境变量设置为 pusher 在你的应用程序的 .env 文件中:
BROADCAST_CONNECTION=pusher最后,您就可以安装和配置Laravel Echo,它将在客户端接收广播事件。
[!NOTE]
下文文档讨论了如何在“Pusher兼容”模式下使用Ably。然而,Ably团队推荐并维护了一个能够利用Ably提供的独特功能的广播器和Echo客户端。有关使用Ably维护的驱动程序的更多信息,请 查阅 Ably 的 Laravel 广播器文档。
为了在使用 Ably 作为事件广播器时,快速启用对 Laravel 广播功能的支持,请调用带 --ably 选项的 install:broadcasting Artisan 命令。此 Artisan 命令将提示您输入 Ably 凭据,安装 Ably PHP 和 JavaScript SDK,并使用相应的变量更新您的应用程序的 .env 文件:
php artisan install:broadcasting --ably在继续之前,您应该在 Ably 应用程序设置中启用 Pusher 协议支持。您可以在 Ably 应用程序设置面板的“协议适配器设置”部分启用此功能。
要手动安装 Ably 支持,您应该使用 Composer 包管理器安装 Ably PHP SDK:
composer require ably/ably-php接下来,您应该在 config/broadcasting.php 配置文件中配置您的 Ably 凭据。此文件中已包含一个 Ably 配置示例,可让您快速指定密钥。通常,此值应通过 ABLY_KEY 环境变量:
ABLY_KEY=your-ably-key然后,设置 BROADCAST_CONNECTION 环境变量为 ably 在你的应用程序的 .env 文件中:
BROADCAST_CONNECTION=ably最后,您已准备好安装和配置Laravel Echo,它将在客户端接收广播事件。
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+。
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[!NOTE]
要了解更多关于编译您的应用程序的 JavaScript 资产的信息,请查阅 Vite 文档。
如果您已经有一个您希望 Echo 使用的预配置的 Pusher Channels 客户端实例,您可以通过 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)
});[!NOTE]
下面的文档讨论了如何在“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 应用程序的设置仪表板中的"协议适配器设置"部分启用此功能。
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,
});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,
});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 公钥。您的公钥是您的 Ably 密钥中在 : 字符之前的部分。
一旦您已根据您的需求调整了 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
{
/**
* The order instance.
*
* @var \App\Models\Order
*/
public $order;
}ShouldBroadcast 接口要求我们的事件定义一个 broadcastOn 方法。此方法负责返回事件应在其上广播的频道。此方法的空存根已在生成的事件类中定义,因此我们只需填写其详细信息。我们只希望订单的创建者能够查看状态更新,因此我们将在绑定到该订单的私有频道上广播该事件:
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
/**
* Get the channel the event should broadcast on.
*/
public function broadcastOn(): Channel
{
return new PrivateChannel('orders.'.$this->order->id);
}如果您希望事件在多个通道上广播,您可以返回一个 array 作为替代:
use Illuminate\Broadcasting\PrivateChannel;
/**
* Get the channels the event should broadcast on.
*
* @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 钩子使其易于上手,并且,默认情况下,事件的所有公共属性都将包含在广播事件中:
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 的实例代表任何用户都可以订阅的公共频道,而 PrivateChannels 和 PresenceChannels 代表需要频道授权的私有频道:
<?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;
/**
* Create a new event instance.
*/
public function __construct(
public User $user,
) {}
/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('user.'.$this->user->id),
];
}
}实现 ShouldBroadcast 接口后,你只需要像平时一样触发事件即可。事件触发后,一个队列任务将使用你指定的广播驱动自动广播该事件。
默认情况下,Laravel 将使用事件的类名广播该事件。但是,您可以通过在该事件上定义一个 broadcastAs 方法来自定义广播名称:
/**
* The event's broadcast name.
*/
public function broadcastAs(): string
{
return 'server.created';
}如果您使用broadcastAs方法自定义广播名称,则应确保使用开头的.字符注册您的监听器。这将指示 Echo 不在事件前加上应用程序的命名空间:
.listen('.server.created', function (e) {
// ...
});当事件被广播时,其所有 public 属性都会自动序列化并作为事件的负载广播,允许你从JavaScript应用中访问其任何公共数据。所以,例如,如果你的事件有一个单一的 public $user 属性,包含一个 Eloquent 模型,事件的广播负载将是:
{
"user": {
"id": 1,
"name": "Patrick Stewart"
...
}
}然而,如果你希望对你的广播负载拥有更细粒度的控制,你可以为你的事件添加一个 broadcastWith 方法。此方法应返回你希望作为事件负载广播的数据数组:
/**
* Get the data to broadcast.
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
return ['id' => $this->user->id];
}默认情况下,每个广播事件都会被放置在你的 queue.php 配置文件中指定的默认队列连接的默认队列上。你可以通过在事件类上定义 connection 和 queue 属性,来自定义广播器使用的队列连接和名称:
/**
* The name of the queue connection to use when broadcasting the event.
*
* @var string
*/
public $connection = 'redis';
/**
* The name of the queue on which to place the broadcasting job.
*
* @var string
*/
public $queue = 'default';或者,您可以自定义队列名称,方法是在您的事件上定义一个 broadcastQueue 方法:
/**
* The name of the queue on which to place the broadcasting job.
*/
public function broadcastQueue(): string
{
return 'default';
}如果您想使用 sync 队列而不是默认的队列驱动程序来广播您的事件,您可以实现 ShouldBroadcastNow 接口而不是 ShouldBroadcast:`
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class OrderShipmentStatusUpdated implements ShouldBroadcastNow
{
// ...
}有时您希望仅当给定条件为真时才广播您的事件。您可以通过向事件类添加一个 broadcastWhen 方法来定义这些条件:
/**
* Determine if this event should broadcast.
*/
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 路由来处理授权请求。如果 Laravel 未能自动注册这些路由,你可以手动在你的应用程序的 /bootstrap/app.php 文件中注册它们:
->withRouting(
web: __DIR__.'/../routes/web.php',
channels: __DIR__.'/../routes/channels.php',
health: '/up',
)接下来,我们需要定义逻辑来实际确定当前已认证用户是否可以侦听给定通道。这在 routes/channels.php 文件中完成,该文件是由 install:broadcasting Artisan 命令创建的。在此文件中,你可以使用 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;
});[!WARNING]
与 HTTP 路由模型绑定不同,频道模型绑定不支持自动隐式模型绑定范围。然而,这通常不是问题,因为大多数频道可以基于单个模型的唯一主键进行范围限定。
私有和在场广播频道通过您应用程序的默认认证守卫认证当前用户。如果用户未经认证,频道授权将自动拒绝,且授权回调永不执行。但是,您可以在必要时分配多个自定义守卫来认证传入请求:
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
{
/**
* Create a new channel instance.
*/
public function __construct() {}
/**
* Authenticate the user's access to the channel.
*/
public function join(User $user, Order $order): array|bool
{
return $user->id === $order->user_id;
}
}[!NOTE]
Like many other classes in Laravel, channel classes will automatically be resolved by the service container. So, you may type-hint any dependencies required by your channel in its constructor.
一旦你定义了一个事件并使用 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 方法来指示广播器不要将该事件广播给当前用户。
[!WARNING]
您的事件必须使用Illuminate\Broadcasting\InteractsWithSocketstrait 才能调用toOthers方法。
当你初始化一个 Laravel Echo 实例,一个 socket ID 会被分配给该连接。如果你正在使用一个全局 Axios 实例从你的 JavaScript 应用程序发起 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;
/**
* Create a new event instance.
*/
public function __construct()
{
$this->broadcastVia('pusher');
}
}有时,您可能希望将一个简单事件广播到应用程序的前端,而无需创建专用的事件类。为了实现这一点,Broadcast 门面允许您广播“匿名事件”:
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 在广播事件时遇到错误时,就会抛出一个异常,这通常会导致最终用户看到应用程序错误。由于事件广播通常是你的应用程序核心功能的补充,你可以通过在事件上实现 ShouldRescue 接口来阻止这些异常破坏用户体验。
实现 ShouldRescue 接口的事件在广播尝试期间会自动使用 Laravel 的 rescue 辅助函数。该辅助函数捕获所有异常,将它们报告给您的应用程序异常处理器以进行日志记录,并允许应用程序正常继续执行而不会中断用户的工作流:
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldRescue;
class ServerCreated implements ShouldBroadcast, ShouldRescue
{
// ...
}一旦您已经 安装并实例化 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');要退出一个频道, 您可以调用 leaveChannel 方法 在 您的 Echo 实例:
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) => {
// ...
});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);
},
);您还可以指定广播事件有效载荷数据的形状,提供更高的类型安全性和编辑便利性:
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);
},
);
// Stop listening without leaving channel...
stopListening();
// Start listening again...
listen();
// Leave channel...
leaveChannel();
// Leave a channel and also its associated private and presence channels...
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);
},
);
// Stop listening without leaving channel...
stopListening();
// Start listening again...
listen();
// Leave channel...
leaveChannel();
// Leave a channel and also its associated private and presence channels...
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>要连接到存在频道,您可以使用 useEchoPresence 钩子:
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>存在频道建立在私有频道的安全性之上,同时公开了一个额外功能,即了解谁订阅了该频道。这使得构建强大的协作式应用程序功能变得容易,例如在另一个用户正在查看同一页面时通知用户,或者列出聊天室的成员。
所有在场频道也都是私有频道;因此,用户必须获得授权才能访问它们。但是,在定义用于在场频道的授权回调时,如果用户被授权加入该频道,您不会返回 true。相反,您应该返回一个关于该用户的数据数组。
由授权回调返回的数据将提供给你的 JavaScript 应用中的在线频道事件监听器。如果用户未被授权加入在线频道,你应该返回 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];
}
});要加入存在频道,您可以使用 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 方法将在用户离开通道时执行。error 方法将在认证端点返回非 200 的 HTTP 状态码时,或在解析返回的 JSON 时出现问题时执行。
存在通道可以像公有或私有通道一样接收事件。以聊天室为例,我们可能想要将 NewMessage 事件广播到房间的存在通道。为此,我们将从事件的 broadcastOn 方法返回一个 PresenceChannel 实例:
/**
* Get the channels the event should broadcast on.
*
* @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 方法监听发送到存在通道的事件:
Echo.join(`chat.${roomId}`)
.here(/* ... */)
.joining(/* ... */)
.leaving(/* ... */)
.listen('NewMessage', (e) => {
// ...
});[!WARNING]
在阅读以下关于模型广播的文档之前,我们建议您熟悉 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;
/**
* Get the user that the post belongs to.
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* Get the channels that model events should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>
*/
public function broadcastOn(string $event): array
{
return [$this, $this->user];
}
}一旦您的模型包含此特性并定义了其广播频道,它将在模型实例被创建、更新、删除、软删除或恢复时开始自动广播事件。
此外,您可能已经注意到,broadcastOn 方法接收一个字符串 $event 参数。此参数包含在模型上发生的事件类型,其值将是 created、updated、deleted、trashed 或 restored。通过检查此变量的值,您可以确定模型应该向哪些频道(如果有的话)广播以响应特定的事件:
/**
* Get the channels that model events should broadcast on.
*
* @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;
/**
* Create a new broadcastable model event for the model.
*/
protected function newBroadcastableEvent(string $event): BroadcastableModelEventOccurred
{
return (new BroadcastableModelEventOccurred(
$this, $event
))->dontBroadcastToCurrentUser();
}正如您可能已经注意到的,上面模型示例中的 broadcastOn 方法没有返回 Channel 实例。相反,Eloquent 模型是直接返回的。如果您的模型的 broadcastOn 方法返回了 Eloquent 模型实例(或者包含在该方法返回的数组中),Laravel 将使用模型的类名和主键标识符作为频道名,自动为该模型实例化一个私有频道实例。
因此,一个 App\Models\User 模型,其 id 为 1,将被转换为一个 Illuminate\Broadcasting\PrivateChannel 实例,名字为 App.Models.User.1。当然,除了从你的模型的 broadcastOn 方法返回 Eloquent 模型实例之外,你还可以返回完整的 Channel 实例,以便完全控制模型的频道名称:
use Illuminate\Broadcasting\PrivateChannel;
/**
* Get the channels that model events should broadcast on.
*
* @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 将会在广播事件时使用上面讨论的模型广播事件命名约定:
/**
* The model event's broadcast name.
*/
public function broadcastAs(string $event): string|null
{
return match ($event) {
'created' => 'post.created',
default => null,
};
}
/**
* Get the data to broadcast for the model.
*
* @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,您可以使用 Laravel Echo 内置的 useEchoModel 钩子来轻松监听模型广播:
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);
});[!NOTE]
当使用 Pusher Channels 时,您必须在您的 应用程序仪表盘 的“应用设置”部分中启用“客户端事件”选项以便发送客户端事件。
有时您可能希望将事件广播给其他已连接的客户端而无需触及您的 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 实例的通知都将被回调接收。用于 App.Models.User.{id} 频道的频道授权回调包含在你的应用的 routes/channels.php 文件中。
如果您想停止接收通知,但又不想离开频道,您可以使用 stopListeningForNotification 方法:
const callback = (notification) => {
console.log(notification.type);
}
// Start listening...
Echo.private(`App.Models.User.${userId}`)
.notification(callback);
// Stop listening (callback must be the same)...
Echo.private(`App.Models.User.${userId}`)
.stopListeningForNotification(callback);