# 廣播系統
- [簡介](#introduction)
- [配置](#configuration)
- [對驅動的要求](#driver-prerequisites)
- [概念綜述](#concept-overview)
- [使用示例程序](#using-example-application)
- [定義廣播事件](#defining-broadcast-events)
- [廣播名稱](#broadcast-name)
- [廣播數據](#broadcast-data)
- [廣播隊列](#broadcast-queue)
- [廣播條件](#broadcast-conditions)
- [授權頻道](#authorizing-channels)
- [定義授權路由](#defining-authorization-routes)
- [定義授權回調](#defining-authorization-callbacks)
- [定義頻道類](#defining-channel-classes)
- [廣播事件](#broadcasting-events)
- [只廣播給他人](#only-to-others)
- [接收廣播](#receiving-broadcasts)
- [安裝 Laravel Echo](#installing-laravel-echo)
- [對事件進行監聽](#listening-for-events)
- [退出頻道](#leaving-a-channel)
- [命名空間](#namespaces)
- [Presence 頻道](#presence-channels)
- [授權 Presence 頻道](#authorizing-presence-channels)
- [加入 Presence 頻道](#joining-presence-channels)
- [廣播到 Presence 頻道](#broadcasting-to-presence-channels)
- [客戶端事件](#client-events)
- [消息通知](#notifications)
<a name="introduction"></a>
## 簡介
在現代的 web 應用程序中, WebSockets 被用來實現實時、即時更新的用戶接口。當服務器上的數據更新后,更新信息會通過 WebSocket 連接發送到客戶端等待處理。相比于不停地輪詢應用程序,這是一種更加可靠和高效的選擇。
為了幫助你構建這類應用, Laravel 將通過 WebSocket 連接來使「廣播」 [事件](/docs/{{version}}/events) 變得更加輕松。 廣播 Laravel 事件允許你在服務端和客戶端 JavaScript 應用程序間共享相同的事件名。
> {注} 在深入了解事件廣播之前,請確認你已閱讀所有關于 Laravel [事件和監聽器](/docs/{{version}}/events) 的文檔。
<a name="configuration"></a>
### 配置
所有關于事件廣播的配置都保存在 `config/broadcasting.php` 配置文件中。 Laravel 自帶了幾個廣播驅動: [Pusher](https://pusher.com) 、 [Redis](/docs/{{version}}/redis) , 和一個用于本地開發與調試的 `log` 驅動。另外,還有一個 `null` 驅動允許你完全關閉廣播系統。每一個驅動的示例配置都可以在 `config/broadcasting.php` 配置文件中找到。
#### 廣播服務提供者
在對事件進行廣播之前,你必須先注冊 `App\Providers\BroadcastServiceProvider` 。對于一個新建的 Laravel 應用程序,你只需要在 `config/app.php` 配置文件的 `providers` 數組中取消對該提供者的注釋即可。該提供者將允許你注冊廣播授權路由和回調。
#### CSRF 令牌
[Laravel Echo](#installing-laravel-echo) 需要訪問當前會話的 CSRF 令牌。你應當驗證你的應用程序的 `head` HTML 元素是否定義了包含 CSRF 令牌的 `meta` 標簽:
<meta name="csrf-token" content="{{ csrf_token() }}">
<a name="driver-prerequisites"></a>
### 對驅動的要求
#### Pusher
如果你使用 [Pusher](https://pusher.com) 來對事件進行廣播,請用 Composer 包管理器來安裝 Pusher PHP SDK :
composer require pusher/pusher-php-server "~3.0"
然后,你需要在 `config/broadcasting.php` 配置文件中配置你的 Pusher 證書。該文件中已經包含了一個 Pusher 示例配置,你可以快速地指定你的 Pusher key 、secret 和 application ID。 `config/broadcasting.php` 文件的 `pusher` 配置項同時也允許你指定 Pusher 支持的額外 `options` ,例如 cluster:
'options' => [
'cluster' => 'eu',
'encrypted' => true
],
當 Pusher 和 [Laravel Echo](#installing-laravel-echo) 一起使用時,你應該在 `resources/assets/js/bootstrap.js` 文件中實例化 Echo 對象時指定 `pusher` 作為所需要的 broadcaster :
import Echo from "laravel-echo"
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key'
});
#### Redis
如果你使用 Redis 廣播器,請安裝 Predis 庫:
composer require predis/predis
Redis 廣播器會使用 Redis 的 發布/訂閱 特性來廣播消息;盡管如此,你仍需將它與能夠從 Redis 接收消息的 WebSocket 服務器配對使用以便將消息廣播到你的 WebSocket 頻道上去。
當 Redis 廣播器發布一個事件的時候,該事件會被發布到它指定的頻道上去,傳輸的數據是一個采用 JSON 編碼的字符串。該字符串包含了事件名、 `data` 數據和生成該事件 socket ID 的用戶(如果可用的話)。
#### Socket.IO
如果你想將 Redis 廣播器 和 Socket.IO 服務器進行配對,你需要在你的應用程序中引入 Socket.IO JavaScript 客戶端庫。你可以通過 NPM 包管理器進行安裝:
npm install --save socket.io-client
然后,你需要在實例化 Echo 時指定 `socket.io` 連接器和 `host` 。
import Echo from "laravel-echo"
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
最后,你需要運行一個與 Laravel 兼容的 Socket.IO 服務器。 Laravel 官方并沒有內置 Socket.IO 服務器實現;不過,可以選擇一個由社區驅動維護的項目 [tlaverdure/laravel-echo-server](https://github.com/tlaverdure/laravel-echo-server) ,目前托管在 GitHub 。
#### 對隊列的要求
在開始廣播事件之前,你還需要配置和運行 [隊列監聽器](/docs/{{version}}/queues) 。所有的事件廣播都是通過隊列任務來完成的,因此應用程序的響應時間不會受到明顯影響。
<a name="concept-overview"></a>
## 概念綜述
Laravel 的事件廣播允許你使用基于驅動的 WebSockets 將服務端的 Laravel 事件廣播到客戶端的 JavaScript 應用程序。當前的 Laravel 自帶了 [Pusher](https://pusher.com) 和 Redis 驅動。通過使用 [Laravel Echo](#installing-laravel-echo) 的 Javascript 包,我們可以很方便地在客戶端消費事件。
事件通過「頻道」來廣播,這些頻道可以被指定為公開或私有的。任何訪客都可以不經授權或認證訂閱一個公開頻道;然而,如果想要訂閱一個私有頻道,那么該用戶必須通過認證,并獲得該頻道的授權。
<a name="using-example-application"></a>
### 使用示例程序
在深入了解事件廣播的每個組件之前,讓我們先用一個電子商務網站作為例子來概覽一下。我們不會討論配置 [Pusher](https://pusher.com) 或者 [Laravel Echo](#installing-laravel-echo) 的細節,這些會在本文檔的其它章節里詳細討論。
在我們的應用程序中,我們假設有一個允許用戶查看訂單配送狀態的頁面。有一個 `ShippingStatusUpdated` 事件會在配送狀態更新時被觸發:
event(new ShippingStatusUpdated($update));
#### `ShouldBroadcast` 接口
當用戶在查看自己的訂單時,我們不希望他們必須通過刷新頁面才能看到狀態更新。我們希望一旦有更新時就主動將更新信息廣播到客戶端。所以,我們必須標記 `ShippingStatusUpdated` 事件實現 `ShouldBroadcast` 接口。這會讓 Laravel 在事件被觸發時廣播該事件:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ShippingStatusUpdated implements ShouldBroadcast
{
/**
* 有關配送狀態更新的信息。
*
* @var string
*/
public $update;
}
`ShouldBroadcast` 接口要求事件定義一個 `broadcastOn` 方法。該方法負責指定事件被廣播到哪些頻道。在(通過 Artisan 命令)生成的事件類中,一個空的 `broadcastOn` 方法已經被預定義好了,所以我們只需要完成其細節即可。我們希望只有訂單的創建者能夠看到狀態的更新,所以我們要把該事件廣播到與這個訂單綁定的私有頻道上去:
/**
* 獲取事件應該廣播的頻道。
*
* @return array
*/
public function broadcastOn()
{
return new PrivateChannel('order.'.$this->update->order_id);
}
#### 授權頻道
記住,用戶只有在被授權之后才能監聽私有頻道。我們可以在 `routes/channels.php` 文件中定義頻道的授權規則。在本例中,我們需要對視圖監聽私有 `order.1` 頻道的所有用戶進行驗證,確保只有訂單真正的創建者才能監聽:
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
`channel` 方法接收兩個參數:頻道名稱和一個回調函數,該回調通過返回 `true` 或者 `false` 來表示用戶是否被授權監聽該頻道。
所有的授權回調接收當前被認證的用戶作為第一個參數,任何額外的通配符參數作為后續參數。在本例中,我們使用 `{orderId}` 占位符來表示頻道名稱的 「ID」 部分是通配符。
#### 對事件廣播進行監聽
接下來,就只剩下在 JavaScript 應用程序中監聽事件了。我們可以通過 Laravel Echo 來實現。首先,我們使用 `private` 方法來訂閱私有頻道。然后,使用 `listen` 方法來監聽 `ShippingStatusUpdated` 事件。默認情況下,事件的所有公有屬性會被包括在廣播事件中:
Echo.private(`order.${orderId}`)
.listen('ShippingStatusUpdated', (e) => {
console.log(e.update);
});
<a name="defining-broadcast-events"></a>
## 定義廣播事件
要告知 Laravel 一個給定的事件需要廣播,只需要在事件類中實現 `Illuminate\Contracts\Broadcasting\ShouldBroadcast` 接口即可。該接口已被導入到所有由框架生成的事件類中,所以你可以很方便地將它添加到你自己的事件中。
`ShouldBroadcast` 接口要求你實現一個方法: `broadcastOn` 。 該方法返回一個頻道或者一個頻道數組,事件會被廣播到這些頻道。這些頻道必須是 `Channel` 、`PrivateChannel` 或者 `PresenceChannel` 的實例。 `Channel` 代表任何用戶都可以訂閱的公開頻道, 而 `PrivateChannels` 和 `PresenceChannels` 則代表需要 [頻道授權](#authorizing-channels) 的私有頻道:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ServerCreated implements ShouldBroadcast
{
use SerializesModels;
public $user;
/**
* 創建一個新的事件實例。
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
*獲得事件廣播的頻道。
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('user.'.$this->user->id);
}
}
然后,你只需要像你平時那樣 [觸發事件](/docs/{{version}}/events) 。一旦事件被觸發,一個 [隊列任務](/docs/{{version}}/queues) 會自動廣播事件到你指定的廣播驅動上。
<a name="broadcast-name"></a>
### 廣播名稱
Laravel 默認會使用事件的類名作為廣播名稱來廣播事件。不過,你也可以在事件類中定義一個 `broadcastAs` 方法來自定義廣播名稱:
/**
* 事件的廣播名稱。
*
* @return string
*/
public function broadcastAs()
{
return 'server.created';
}
如果你使用了 `broadcastAs` 方法來自定義廣播名稱,你應當確保在你注冊監聽器時加上一個 `.` 的前綴。這將指示 Echo 不要在事件之前添加應用程序的命名空間:
.listen('.server.created', function (e) {
....
});
<a name="broadcast-data"></a>
### 廣播數據
當一個事件被廣播時,其所有的 `public` 屬性都會自動序列化并作為事件有效載荷進行廣播,這允許你在 JavaScript 應用程序中訪問到事件所有的公有數據。舉個例子,如果你的事件有一個單獨的包含了一個 Eloquent 模型的公有 `$user` 屬性,那么事件的廣播有效載荷將會是:
{
"user": {
"id": 1,
"name": "Patrick Stewart"
...
}
}
不過,如果你想更細粒度地控制你的廣播有效載荷,你可以向你的事件中添加一個 `broadcastWith` 方法。這個方法會返回一個你想要作為事件有效載荷進行廣播的數據數組:
/**
* 指定廣播數據。
*
* @return array
*/
public function broadcastWith()
{
return ['id' => $this->user->id];
}
<a name="broadcast-queue"></a>
### 廣播隊列
默認情況下,每一個廣播事件都會被推送到在 `queue.php` 配置文件中指定的默認隊列連接相應的默認隊列中。你可以在事件類中定義一個 `broadcastQueue` 屬性來自定義廣播器所使用的隊列。該屬性需要你指定廣播時你想要用的隊列名稱:
/**
* 事件被推送到的隊列名稱。
*
* @var string
*/
public $broadcastQueue = 'your-queue-name';
如果你想使用 `sync` 隊列而不是默認隊列驅動來廣播事件,你可以實現 `ShouldBroadcastNow` 接口而不是 `ShouldBroadcast` :
<?php
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class ShippingStatusUpdated implements ShouldBroadcastNow
{
//
}
<a name="broadcast-conditions"></a>
### 廣播條件
有時,你想在給定條件為 true 的情況下才廣播你的事件。你可以通過在事件類中添加一個 `broadcastWhen` 方法來定義這些條件:
/**
* 判定事件是否可以廣播。
*
* @return bool
*/
public function broadcastWhen()
{
return $this->value > 100;
}
<a name="authorizing-channels"></a>
## 授權頻道
對于私有頻道,用戶只有被授權之后才能監聽。實現過程是用戶向你的 Laravel 應用程序發起一個攜帶頻道名稱的 HTTP 請求,由你的應用程序判斷該用戶是否能夠監聽該頻道。在使用 [Laravel Echo](#installing-laravel-echo) 時,授權訂閱私有頻道的 HTTP 請求會自動發送;盡管如此,你仍需定義相應的路由來響應這些請求。
<a name="defining-authorization-routes"></a>
### 定義授權路由
幸運的是,在 Laravel 中我們可以很容易地定義路由來響應頻道授權請求。在 Laravel 自帶的 `BroadcastServiceProvider` 中,你可以看到對 `Broadcast::routes` 方法的調用。該方法會注冊 `/broadcasting/auth` 路由來處理授權請求:
Broadcast::routes();
`Broadcast::routes` 方法會自動將它的路由置入 `web` 中間件組中;不過,如果你想自定義指定的屬性,你可以向該方法傳遞一個路由屬性數組:
Broadcast::routes($attributes);
#### 自定義授權端點
默認情況下,Echo 將使用 `/broadcasting/auth` 端點來授權頻道訪問。 但是,您可以通過將 `authEndpoint` 配置選項傳遞給 Echo 實例來指定自己的授權端點:
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
authEndpoint: '/custom/endpoint/auth'
});
<a name="defining-authorization-callbacks"></a>
### 定義授權回調
接下來,我們需要定義真正用于處理頻道授權的邏輯。該邏輯在應用程序自帶的 `routes/channels.php` 文件中完成。在這個文件中,你可以使用 `Broadcast::channel` 方法來注冊頻道授權回調:
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
`channel` 方法接收兩個參數:頻道名稱和一個回調函數,該回調通過返回 `true` 或者 `false` 來表示用戶是否被授權監聽該頻道。
所有的授權回調接收當前認證用戶作為第一個參數,任何額外的通配符參數作為后續參數。在本例中,我們使用 `{orderId}` 占位符來表示頻道名稱的 「ID」 部分是通配符。
#### 授權回調模型綁定
就像 HTTP 路由一樣,頻道路由也可以利用顯式或隱式 [路由模型綁定](/docs/{{version}}/routing#route-model-binding) 。例如,你可以請求接收一個真正的 `Order` 模型實例,而不是字符串或數字類型的 order ID:
use App\Order;
Broadcast::channel('order.{order}', function ($user, Order $order) {
return $user->id === $order->user_id;
});
#### 授權回調驗證
私有頻道和在線廣播頻道通過應用程序的默認授權驗證對當前用戶身份進行驗證。 如果用戶未經過授權驗證,則會自動拒絕通道授權,并且永遠不會執行授權回調。 但是,您可以分配多個自定義防護,以便在必要時對傳入請求進行身份驗證:
Broadcast::channel('channel', function() {
// ...
}, ['guards' => ['web', 'admin']])
<a name="defining-channel-classes"></a>
### 定義頻道類
如果你的應用程序用到了許多不同的頻道,你的 `routes/channels.php` 文件可能會變得很龐大。所以,你可以使用頻道類來代替使用閉包授權頻道。要生成一個頻道類,請使用 `make:channel` Artisan 命令。該命令會在 `App/Broadcasting` 目錄中放置一個新的頻道類。
php artisan make:channel OrderChannel
接下來,在你的 `routes/channels.php` 文件中注冊你的頻道:
use App\Broadcasting\OrderChannel;
Broadcast::channel('order.{order}', OrderChannel::class);
最后,你可以將頻道的授權邏輯放入頻道類的 `join` 方法中。該 `join` 方法將保存你通常放置在頻道授權閉包中的相同邏輯。當然,你也可以利用頻道模型綁定:
<?php
namespace App\Broadcasting;
use App\User;
use App\Order;
class OrderChannel
{
/**
* 創建一個新的頻道實例。
*
* @return void
*/
public function __construct()
{
//
}
/**
* 認證用戶的頻道訪問權限。
*
* @param \App\User $user
* @param \App\Order $order
* @return array|bool
*/
public function join(User $user, Order $order)
{
return $user->id === $order->user_id;
}
}
> {注} 就像 Laravel 中的很多其它類,頻道類會通過 [服務容器](/docs/{{version}}/container) 自動解析。因此,你可以在頻道類的構造函數中對其進行所需依賴項的類型提示。
<a name="broadcasting-events"></a>
## 廣播事件
定義好一個事件且將其標記實現 `ShouldBroadcast` 接口之后,你所要做的僅僅是通過 `event` 函數來觸發該事件。事件分發器會識別出標記了實現 `ShouldBroadcast` 接口的事件,并將其推送到隊列中進行廣播:
event(new ShippingStatusUpdated($update));
<a name="only-to-others"></a>
### 只廣播給他人
當創建一個會用到事件廣播的應用程序時,你可以使用 `broadcast` 函數來代替 `event` 。和 `event` 函數一樣, `broadcast` 函數將事件分發到服務端監聽器:
broadcast(new ShippingStatusUpdated($update));
不過, `broadcast` 函數還有一個允許你將當前用戶排除在廣播接收者之外的 `toOthers` 方法:
broadcast(new ShippingStatusUpdated($update))->toOthers();
為了更好地理解什么時候使用 `toOthers` 方法,讓我們假設有一個任務列表的應用程序,用戶可以通過輸入任務名來新建任務。要新建任務,你的應用程序需要發起一個請求到一個 `/task` 路由,該路由會廣播任務的創建,并返回新任務的 JSON 響應。當你的 JavaScript 應用程序從路由收到響應后,它會直接將新任務插入到任務列表中,就像這樣:
axios.post('/task', task)
.then((response) => {
this.tasks.push(respo
});
然而,別忘了,我們還廣播了任務的創建。如果你的 JavaScript 應用程序正在監聽該事件以便添加任務至任務列表,任務列表中將出現重復的任務:一個來自路由響應,另一個來自廣播。你可以通過使用 `toOthers` 方法告知廣播器不要將事件廣播到當前用戶來解決這個問題。
> {注} 為了能調用 `toOthers` 方法,你的事件必須使用 `Illuminate\Broadcasting\InteractsWithSockets` trait 。
#### 配置
當你初始化 Laravel Echo 實例的時候,一個套接字 ID 會被分配到該連接。如果你使用了 [Vue](https://vuejs.org) 和 [Axios](https://github.com/mzabriskie/axios) ,該套接字 ID 會自動地以 `X-Socket-ID` 頭的方式添加到每一個傳出請求中。那么,當你調用 `toOthers` 方法時,Laravel 會從請求頭中取出套接字 ID ,并告知廣播器不要廣播任何消息到帶有這個套接字 ID 的連接上。
你如果你沒有使用 Vue 和 Axios ,則需要手動配置 JavaScript 應用程序來發送 `X-Socket-ID` 請求頭。你可以用 `Echo.socketId` 方法來獲取套接字 ID :
var socketId = Echo.socketId();
<a name="receiving-broadcasts"></a>
## 接收廣播
<a name="installing-laravel-echo"></a>
### 安裝 Laravel Echo
Laravel Echo 是一個 JavaScript 庫,有了這個庫之后,訂閱頻道監聽 Laravel 廣播的事件變得非常容易。你可以通過 NPM 包管理器來安裝 Echo 。在本例中,因為我們會使用 Pusher 廣播器,所以我們也會安裝 `pusher-js` 包:
npm install --save laravel-echo pusher-js
安裝好 Echo 之后,你就可以在應用程序的 JavaScript 中創建一個全新的 Echo 實例。做這件事的一個理想的地方是在 Laravel 框架自帶的 `resources/js/bootstrap.js` 文件的底部:
import Echo from "laravel-echo"
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key'
});
當你使用 `pusher` 連接器來創建一個 Echo 實例的時候,還可以指定 `cluster` 以及連接是否需要加密:
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
cluster: 'eu',
encrypted: true
});
#### 使用現有客戶端實例
如果您已經有一個希望 Echo 使用的 Pusher 或 Socket.io 客戶端實例,您可以通過 `client` 配置選項將其傳遞給Echo:
const client = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
client: client
});
<a name="listening-for-events"></a>
### 對事件進行監聽
安裝并實例化 Echo 之后, 你就可以開始監聽事件廣播了。首先,使用 `channel` 方法獲取一個頻道實例,然后調用 `listen` 方法來監聽指定的事件:
Echo.channel('orders')
.listen('OrderShipped', (e) => {
console.log(e.order.name);
});
如果你想監聽私有頻道上的事件,請使用 `private` 方法。你可以通過鏈式調用 `listen` 方法來監聽單個頻道上的多個事件:
Echo.private('orders')
.listen(...)
.listen(...)
.listen(...);
<a name="leaving-a-channel"></a>
### 退出頻道
要離開頻道,您可以在Echo實例上調用 `leaveChannel` 方法:
Echo.leaveChannel('orders');
如果您想離開私有頻道和在線頻道,您可以調用 `leave` 方法:
Echo.leave('orders');
<a name="namespaces"></a>
### 命名空間
你可能已經注意到在上面的例子中,我們并沒有為事件類指定完整的命名空間。這是因為 Echo 會默認事件都在 `App\Events` 命名空間下。不過,你可以在實例化 Echo 時傳遞一個 `namespace` 配置項來指定根命名空間:
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
namespace: 'App.Other.Namespace'
});
另外,你可以在使用 Echo 訂閱事件的時候為事件類加上 `.` 前綴。這樣就可以指定完全限定名稱的類名了:
Echo.channel('orders')
.listen('.Namespace.Event.Class', (e) => {
//
});
<a name="presence-channels"></a>
## Presence 頻道
Presence 頻道構建在私有頻道的安全性基礎之上,并提供了額外的特性:獲知誰訂閱了該頻道。這一點使構建強大的,協同的應用變得非常容易,比如一個用戶在瀏覽頁面時,通知其他正在瀏覽相同頁面的用戶。
<a name="authorizing-presence-channels"></a>
### 授權 Presence 頻道
所有的 presence 頻道也是私有頻道;因此,用戶必須被 [授權之后才能訪問](#authorizing-channels) 。不過,在給 presence 頻道定義授權回調函數時,如果一個用戶已經加入了該頻道,那么不應該返回 `true` ,而應該返回一個關于該用戶信息的數組。
由授權回調函數返回的數據能夠在你的 JavaScript 應用程序中被 presence 頻道事件監聽器所使用。如果用戶沒有被授權加入該 presence 頻道,那么你應該返回 `false` 或者 `null` :
Broadcast::channel('chat.{roomId}', function ($user, $roomId) {
if ($user->canJoinRoom($roomId)) {
return ['id' => $user->id, 'name' => $user->name];
}
});
<a name="joining-presence-channels"></a>
### 加入 Presence 頻道
你可以使用 Echo 的 `join` 方法來加入 presence 頻道。 `join` 方法會返回一個實現了 `PresenceChannel` 的對象,通過暴露 `listen` 方法,允許你訂閱 `here` 、 `joining` 和 `leaving` 事件。
Echo.join(`chat.${roomId}`)
.here((users) => {
//
})
.joining((user) => {
console.log(user.name);
})
.leaving((user) => {
console.log(user.name);
});
`here` 回調函數會在你成功加入頻道后被立即執行,并接收一個包含其他所有當前訂閱該頻道的用戶的用戶信息數組 。 `joining` 方法會在新用戶加入頻道時被執行,而 `leaving` 方法會在用戶退出頻道時被執行。
<a name="broadcasting-to-presence-channels"></a>
### 廣播到 Presence 頻道
Presence 頻道可以像公開和私有頻道一樣接收事件。使用一個聊天室的例子,我們可能想把 `NewMessage` 事件廣播到聊天室的 presence 頻道。要實現它,我們將從事件的 `broadcastOn` 方法中返回一個 `PresenceChannel` 實例:
/**
* 獲得事件廣播的頻道。
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PresenceChannel('room.'.$this->message->room_id);
}
就像公開或私有事件, presence 頻道事件也可以使用 `broadcast` 函數來廣播。同樣的,你也可以使用 `toOthers` 方法將當前用戶排除在廣播接收者之外:
broadcast(new NewMessage($message));
broadcast(new NewMessage($message))->toOthers();
你可以通過 Echo 的 `listen` 方法來監聽 join 事件:
Echo.join(`chat.${roomId}`)
.here(...)
.joining(...)
.leaving(...)
.listen('NewMessage', (e) => {
//
});
<a name="client-events"></a>
## 客戶端事件
> {注} 使用 [Pusher](https://pusher.com) 時,如果要發送客戶端事件,你必須在 [應用后臺](https://dashboard.pusher.com/) 的「應用設置」部分啟用「客戶端事件」選項。
有時,你可能希望廣播一個事件給其它已經連接的客戶端,但不通知你的 Laravel 應用程序。這在處理「輸入中」這類事情的通知時尤其有用,比如提醒你應用的用戶,另一個用戶正在給定屏幕上輸入信息。
你可以使用 Echo 的 `whisper` 方法來廣播客戶端事件:
Echo.private('chat')
.whisper('typing', {
name: this.user.name
});
你可以使用 `listenForWhisper` 方法來監聽客戶端事件:
Echo.private('chat')
.listenForWhisper('typing', (e) => {
console.log(e.name);
});
<a name="notifications"></a>
## 消息通知
通過與將事件廣播與 [消息通知](/docs/{{version}}/notifications) 配對,你的 JavaScript 應用程序可以在不刷新頁面的情況下接收新的消息通知。在此之前,請確保你已經讀過了如何使用 [廣播通知頻道](/docs/{{version}}/notifications#broadcast-notifications) 的文檔。
配置好使用廣播頻道的消息通知后,你可以使用 Echo 的 `notification` 方法來監聽廣播事件。謹記,頻道名稱應該和接收消息通知的實體類名相匹配:
Echo.private(`App.User.${userId}`)
.notification((notification) => {
console.log(notification.type);
});
在本例中,所有通過 `broadcast` 頻道發送到 `App\User` 實例的消息通知都會被回調接收。一個針對 `App.User.{id}` 頻道的授權回調函數已經包含在 Laravel 框架內置的 `BroadcastServiceProvider` 中了。
- 入門指南
- 安裝
- 部署
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- URL
- Session
- 表單驗證
- 錯誤
- 日志
- 前端開發
- Blade 模板
- 本地化
- 腳手架
- 編譯資源 Mix
- 安全相關
- 用戶認證
- API 認證
- 綜合話題
- 命令行
- 廣播
- 緩存
- 集合
- 事件
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 速查表
- Artisan
- Auth
- Blade
- Cache
- Collection
- Composer
- Config
- Container
- Cookie
- DB
- Environment
- Event
- File
- Helper
- Input
- Lang
- Log
- Model
- Pagination
- Queue
- Redirect
- Request
- Response
- Route
- SSH
- Schema
- Security
- Session
- Storage
- String
- URL
- UnitTest
- Validation
- View