Broadcasting
- Introduction
- Quickstart
- Server Side Installation
- Client Side Installation
- Concept Overview
- Defining Broadcast Events
- Authorizing Channels
- Broadcasting Events
- Receiving Broadcasts
- Presence Channels
- Model Broadcasting
- Client Events
- Notifications
Introduction
最新の Web アプリケーションの多くでは、リアルタイムのライブ更新ユーザー インターフェイスを実装するために WebSocket が使用されています。サーバー上で一部のデータが更新されると、通常、メッセージが WebSocket 接続経由で送信され、クライアントによって処理されます。 WebSocket は、UI に反映する必要があるデータ変更をアプリケーションのサーバーに継続的にポーリングするより効率的な代替手段を提供します。
たとえば、アプリケーションがユーザーのデータを CSV ファイルにエクスポートし、電子メールで送信できると想像してください。ただし、この CSV ファイルの作成には数分かかるため、queued job 内で CSV を作成してメールで送信することを選択します。 CSV が作成され、ユーザーにメールで送信されたら、イベント ブロードキャストを使用して、アプリケーションの JavaScript が受信する App\Events\UserDataExported イベントを送出できます。イベントを受信すると、ページを更新しなくても、CSV が電子メールで送信されたことを示すメッセージをユーザーに表示できます。
この種の機能の構築を支援するために、Laravel では、WebSocket 接続を介してサーバー側 Laravel events を簡単に「ブロードキャスト」できるようにしています。 Laravel イベントをブロードキャストすると、サーバー側の Laravel アプリケーションとクライアント側の JavaScript アプリケーションの間で同じイベント名とデータを共有できます。
ブロードキャストの背後にある中心的な概念は単純です。クライアントはフロントエンドの名前付きチャネルに接続し、Laravel アプリケーションはバックエンドのこれらのチャネルにイベントをブロードキャストします。これらのイベントには、フロントエンドで利用できるようにしたい追加データを含めることができます。
Supported Drivers
デフォルトでは、Laravel には、Laravel Reverb、Pusher Channels、および Ably から選択できる 3 つのサーバー側ブロードキャスト ドライバが含まれています。
イベントブロードキャストに入る前に、events and listeners にある Laravel のドキュメントを必ず読んでください。
Quickstart
デフォルトでは、新しい Laravel アプリケーションではブロードキャストは有効になっていません。 install:broadcasting Artisan コマンドを使用してブロードキャストを有効にすることができます。
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 コマンドを実行すると作成されます。
Next Steps
イベント ブロードキャストを有効にすると、defining broadcast events と listening for events について詳しく学ぶことができます。 Laravel の React、Vue、または Svelte starter kits を使用している場合は、Echo の useEcho hook を使用してイベントをリッスンできます。
イベントをブロードキャストする前に、まず queue worker を構成して実行する必要があります。すべてのイベント ブロードキャストはキューに入れられたジョブを介して行われるため、ブロードキャストされるイベントによってアプリケーションの応答時間が重大な影響を受けることはありません。
Server Side Installation
Laravel のイベントブロードキャストの使用を開始するには、Laravel アプリケーション内でいくつかの設定を行い、いくつかのパッケージをインストールする必要があります。
イベントのブロードキャストは、Laravel イベントをブロードキャストするサーバー側ブロードキャスト ドライバによって実現され、Laravel Echo (JavaScript ライブラリ) がブラウザー クライアント内でイベントを受信できるようになります。心配しないでください。インストール プロセスの各部分を段階的に説明します。
Reverb
イベント ブロードキャスタとして Reverb を使用しているときに Laravel のブロードキャスト機能のサポートをすぐに有効にするには、--reverb オプションを指定して install:broadcasting Artisan コマンドを呼び出します。この Artisan コマンドは、Reverb に必要な Composer および NPM パッケージをインストールし、アプリケーションの .env ファイルを適切な変数で更新します。
php artisan install:broadcasting --reverb
Manual Installation
install:broadcasting コマンドを実行すると、Laravel Reverb をインストールするように求められます。もちろん、Composer パッケージ マネージャーを使用して Reverb を手動でインストールすることもできます。
composer require laravel/reverb
パッケージがインストールされたら、Reverb のインストール コマンドを実行して構成を公開し、Reverb に必要な環境変数を追加して、アプリケーションでのイベント ブロードキャストを有効にすることができます。
php artisan reverb:install
Reverb のインストールと使用方法の詳細については、Reverb documentation を参照してください。
Pusher Channels
イベント ブロードキャスタとして Pusher を使用しているときに、Laravel のブロードキャスト機能のサポートをすぐに有効にするには、--pusher オプションを指定して install:broadcasting Artisan コマンドを呼び出します。この Artisan コマンドは、Pusher 資格情報の入力を求め、Pusher PHP および JavaScript SDK をインストールし、適切な変数を使用してアプリケーションの .env ファイルを更新します。
php artisan install:broadcasting --pusher
Manual Installation
Pusher サポートを手動でインストールするには、Composer パッケージ マネージャーを使用して Pusher Channels PHP SDK をインストールする必要があります。
composer require pusher/pusher-php-server
次に、config/broadcasting.php 構成ファイルでプッシャー チャネルの資格情報を構成する必要があります。このファイルにはプッシャー チャネル構成の例がすでに含まれており、キー、シークレット、アプリケーション ID をすばやく指定できます。通常、アプリケーションの .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"
config/broadcasting.php ファイルの pusher 構成では、クラスターなどのチャネルでサポートされる追加の options を指定することもできます。
次に、アプリケーションの .env ファイルで、BROADCAST_CONNECTION 環境変数を pusher に設定します。
BROADCAST_CONNECTION=pusher
最後に、クライアント側でブロードキャスト イベントを受信する Laravel Echo をインストールして構成する準備が整いました。
Ably
以下のドキュメントでは、Ably を「プッシャー互換性」モードで使用する方法について説明しています。ただし、Ably チームは、Ably が提供する独自の機能を活用できるブロードキャスタと Echo クライアントを推奨し、維持しています。 Ably が保守するドライバの使用の詳細については、consult Ably's Laravel broadcaster documentation を参照してください。
Ably をイベント ブロードキャスタとして使用しているときに Laravel のブロードキャスト機能のサポートをすぐに有効にするには、--ably オプションを指定して install:broadcasting Artisan コマンドを呼び出します。この Artisan コマンドは、Ably 認証情報の入力を求め、Ably PHP および JavaScript SDK をインストールし、適切な変数を使用してアプリケーションの .env ファイルを更新します。
php artisan install:broadcasting --ably
続行する前に、Ably アプリケーション設定でプッシャー プロトコルのサポートを有効にする必要があります。 Ably アプリケーションの設定ダッシュボードの「プロトコル アダプター設定」部分でこの機能を有効にすることができます。
Manual Installation
Ably サポートを手動でインストールするには、Composer パッケージ マネージャーを使用して Ably PHP SDK をインストールする必要があります。
composer require ably/ably-php
次に、config/broadcasting.php 構成ファイルで Ably 認証情報を構成する必要があります。このファイルには、Ably 構成の例がすでに含まれているため、キーをすばやく指定できます。通常、この値は ABLY_KEY environment variable を介して設定する必要があります。
ABLY_KEY=your-ably-key
次に、アプリケーションの .env ファイルで、BROADCAST_CONNECTION 環境変数を ably に設定します。
BROADCAST_CONNECTION=ably
最後に、クライアント側でブロードキャスト イベントを受信する Laravel Echo をインストールして構成する準備が整いました。
Client Side Installation
Reverb
Laravel Echo は、チャンネルのサブスクライブや、サーバー側のブロードキャスト ドライバによってブロードキャストされるイベントのリッスンを簡単に行うことができる JavaScript ライブラリです。
install:broadcasting Artisan コマンドを使用して Laravel Reverb をインストールすると、Reverb と Echo のスキャフォールディングと構成がアプリケーションに自動的に挿入されます。ただし、Laravel Echo を手動で構成したい場合は、以下の手順に従って行うことができます。
Manual Installation
アプリケーションのフロントエンド用に Laravel Echo を手動で構成するには、Reverb が WebSocket サブスクリプション、チャネル、およびメッセージにプッシャー プロトコルを利用するため、まず pusher-js パッケージをインストールします。
npm install --save-dev laravel-echo pusher-js
Echo をインストールすると、アプリケーションの JavaScript で新しい Echo インスタンスを作成できるようになります。これを行うのに最適な場所は、Laravel フレームワークに含まれる resources/js/app.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'],
});
import { configureEcho } from "@laravel/echo-svelte";
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 を手動で構成したい場合は、以下の手順に従って行うことができます。
Manual Installation
アプリケーションのフロントエンド用に Laravel Echo を手動で構成するには、まず WebSocket サブスクリプション、チャネル、メッセージにプッシャー プロトコルを利用する laravel-echo および pusher-js パッケージをインストールします。
npm install --save-dev laravel-echo pusher-js
Echo がインストールされたら、アプリケーションの resources/js/app.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"],
});
import { configureEcho } from "@laravel/echo-svelte";
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 ファイルでプッシャー環境変数の適切な値を定義する必要があります。これらの変数が .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 のドキュメントを参照してください。
Using an Existing Client Instance
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
以下のドキュメントでは、Ably を「プッシャー互換性」モードで使用する方法について説明しています。ただし、Ably チームは、Ably が提供する独自の機能を活用できるブロードキャスタと Echo クライアントを推奨し、維持しています。 Ably が保守するドライバの使用の詳細については、consult Ably's Laravel broadcaster documentation を参照してください。
Laravel Echo は、チャンネルのサブスクライブや、サーバー側のブロードキャスト ドライバによってブロードキャストされるイベントのリッスンを簡単に行うことができる JavaScript ライブラリです。
install:broadcasting --ably Artisan コマンドを使用してブロードキャスト サポートをインストールすると、Ably と Echo のスキャフォールディングと構成がアプリケーションに自動的に挿入されます。ただし、Laravel Echo を手動で構成したい場合は、以下の手順に従って行うことができます。
Manual Installation
アプリケーションのフロントエンド用に Laravel Echo を手動で構成するには、まず WebSocket サブスクリプション、チャネル、メッセージにプッシャー プロトコルを利用する laravel-echo および pusher-js パッケージをインストールします。
npm install --save-dev laravel-echo pusher-js
続行する前に、Ably アプリケーション設定でプッシャー プロトコルのサポートを有効にする必要があります。 Ably アプリケーションの設定ダッシュボードの「プロトコル アダプター設定」部分でこの機能を有効にすることができます。
Echo がインストールされたら、アプリケーションの resources/js/app.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,
});
import { configureEcho } from "@laravel/echo-svelte";
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 のドキュメントを参照してください。
Concept Overview
Laravel のイベント ブロードキャストを使用すると、WebSocket へのドライバベースのアプローチを使用して、サーバー側の Laravel イベントをクライアント側の JavaScript アプリケーションにブロードキャストできます。現在、Laravel には Laravel Reverb、Pusher Channels、および Ably ドライバが同梱されています。イベントは、Laravel Echo JavaScript パッケージを使用してクライアント側で簡単に使用できます。
イベントは、パブリックまたはプライベートとして指定できる「チャネル」を介してブロードキャストされます。アプリケーションへの訪問者は誰でも、認証や許可なしでパブリック チャネルに登録できます。ただし、プライベート チャネルに登録するには、ユーザーが認証され、そのチャネルでリッスンする権限が与えられている必要があります。
Using an Example Application
イベント ブロードキャストの各コンポーネントに入る前に、電子商取引ストアを例として使用して概要を見てみましょう。
このアプリケーションでは、ユーザーが注文の配送ステータスを表示できるページがあると仮定します。また、出荷ステータスの更新がアプリケーションによって処理されるときに、OrderShipmentStatusUpdated イベントが発生すると仮定します。
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
The ShouldBroadcast Interface
ユーザーが注文の 1 つを表示しているときに、ステータスの更新を表示するためにページを更新する必要がないようにしたいと考えています。代わりに、更新が作成されたときにアプリケーションに更新をブロードキャストしたいと考えています。したがって、OrderShipmentStatusUpdated イベントを ShouldBroadcast インターフェイスでマークする必要があります。これにより、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),
// ...
];
}
Authorizing Channels
ユーザーはプライベート チャネルでリッスンすることを許可されている必要があることに注意してください。アプリケーションの 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 を返すコールバックの 2 つの引数を受け入れます。
すべての認可コールバックは、現在認証されているユーザーを最初の引数として受け取り、追加のワイルドカード パラメーターを後続の引数として受け取ります。この例では、{orderId} プレースホルダーを使用して、チャネル名の「ID」部分がワイルドカードであることを示しています。
Listening for Event Broadcasts
次に残っているのは、JavaScript アプリケーションでイベントをリッスンすることだけです。これは、Laravel Echo を使用して行うことができます。 Laravel Echo に組み込まれている React、Vue、Svelte フックを使用すると簡単に始めることができ、デフォルトでは、イベントのすべてのパブリック プロパティがブロードキャスト イベントに含まれます。
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>
<script>
import { useEcho } from "@laravel/echo-svelte";
useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
</script>
Defining Broadcast Events
特定のイベントをブロードキャストする必要があることを Laravel に通知するには、イベント クラスに Illuminate\Contracts\Broadcasting\ShouldBroadcast インターフェイスを実装する必要があります。このインターフェイスは、フレームワークによって生成されたすべてのイベント クラスにすでにインポートされているため、任意のイベントに簡単に追加できます。
ShouldBroadcast インターフェイスでは、単一のメソッド broadcastOn を実装する必要があります。 broadcastOn メソッドは、イベントがブロードキャストされるチャネルまたはチャネルの配列を返す必要があります。チャネルは、Channel、PrivateChannel、または PresenceChannel のインスタンスである必要があります。 Channel のインスタンスは、任意のユーザーが購読できるパブリック チャネルを表し、PrivateChannels および PresenceChannels は、channel authorization を必要とするプライベート チャネルを表します。
<?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 インターフェイスを実装した後は、通常どおり fire the event を実行するだけです。イベントが発生すると、queued job は指定したブロードキャスト ドライバを使用してイベントを自動的にブロードキャストします。
Broadcast Name
デフォルトでは、Laravel はイベントのクラス名を使用してイベントをブロードキャストします。ただし、イベントで broadcastAs メソッドを定義することで、ブロードキャスト名をカスタマイズできます。
/**
* The event's broadcast name.
*/
public function broadcastAs(): string
{
return 'server.created';
}
broadcastAs メソッドを使用してブロードキャスト名をカスタマイズする場合は、先頭に . 文字を使用してリスナを登録する必要があります。これにより、アプリケーションの名前空間をイベントの前に付加しないように Echo に指示されます。
.listen('.server.created', function (e) {
// ...
});
Broadcast Data
イベントがブロードキャストされると、そのすべての public プロパティが自動的にシリアル化され、イベントのペイロードとしてブロードキャストされるため、JavaScript アプリケーションからそのパブリック データのいずれかにアクセスできるようになります。したがって、たとえば、イベントに Eloquent モデルを含む単一のパブリック $user プロパティがある場合、イベントのブロードキャスト ペイロードは次のようになります。
{
"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];
}
Broadcast Queue
デフォルトでは、各ブロードキャスト イベントは、queue.php 構成ファイルで指定されたデフォルト キュー接続のデフォルト キューに配置されます。イベント クラスの Connection 属性と Queue 属性を使用して、ブロードキャスタが使用するキュー接続と名前をカスタマイズできます。
use Illuminate\Queue\Attributes\Connection;
use Illuminate\Queue\Attributes\Queue;
#[Connection('redis')]
#[Queue('default')]
class ServerCreated implements ShouldBroadcast
{
// ...
}
あるいは、イベントで broadcastQueue メソッドを定義してキュー名をカスタマイズすることもできます。
/**
* The name of the queue on which to place the broadcasting job.
*/
public function broadcastQueue(): string
{
return 'default';
}
デフォルトのキュードライバの代わりに sync キューを使用してイベントをブロードキャストする場合は、ShouldBroadcast の代わりに ShouldBroadcastNow インターフェイスを実装できます。
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class OrderShipmentStatusUpdated implements ShouldBroadcastNow
{
// ...
}
Broadcast Conditions
特定の条件が true の場合にのみイベントをブロードキャストしたい場合があります。これらの条件は、イベント クラスに broadcastWhen メソッドを追加することで定義できます。
/**
* Determine if this event should broadcast.
*/
public function broadcastWhen(): bool
{
return $this->order->value > 100;
}
Broadcasting and Database Transactions
ブロードキャスト イベントがデータベース トランザクション内でディスパッチされると、データベース トランザクションがコミットされる前にキューによって処理される場合があります。この問題が発生すると、データベース トランザクション中にモデルまたはデータベース レコードに対して行った更新がまだデータベースに反映されていない可能性があります。さらに、トランザクション内で作成されたモデルやデータベース レコードはデータベースに存在しない可能性があります。イベントがこれらのモデルに依存している場合、イベントをブロードキャストするジョブの処理時に予期しないエラーが発生する可能性があります。
キュー接続の 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;
}
これらの問題の回避方法の詳細については、queued jobs and database transactions に関するドキュメントを参照してください。
Authorizing Channels
プライベート チャネルでは、現在認証されているユーザーが実際にチャネルをリッスンできることを承認する必要があります。これは、チャンネル名を使用して 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',
)
Defining Authorization Callbacks
次に、現在認証されているユーザーが特定のチャンネルを聞くことができるかどうかを実際に判断するロジックを定義する必要があります。これは、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 を返すコールバックの 2 つの引数を受け入れます。
すべての認可コールバックは、現在認証されているユーザーを最初の引数として受け取り、追加のワイルドカード パラメーターを後続の引数として受け取ります。この例では、{orderId} プレースホルダーを使用して、チャネル名の「ID」部分がワイルドカードであることを示しています。
channel:list Artisan コマンドを使用して、アプリケーションのブロードキャスト認可コールバックのリストを表示できます。
php artisan channel:list
Authorization Callback Model Binding
HTTP ルートと同様に、チャネル ルートも暗黙的および明示的な route model binding を利用できます。たとえば、文字列または数値の注文 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 ルート モデル バインディングとは異なり、チャネル モデル バインディングは自動 implicit model binding scoping をサポートしません。ただし、ほとんどのチャネルは単一モデルの一意の主キーに基づいてスコープを設定できるため、これが問題になることはほとんどありません。
Authorization Callback Authentication
プライベート ブロードキャスト チャネルとプレゼンス ブロードキャスト チャネルは、アプリケーションのデフォルトの認証ガードを介して現在のユーザーを認証します。ユーザーが認証されていない場合、チャネル承認は自動的に拒否され、承認コールバックは実行されません。ただし、必要に応じて、受信リクエストを認証する複数のカスタム ガードを割り当てることができます。
Broadcast::channel('channel', function () {
// ...
}, ['guards' => ['web', 'admin']]);
Defining Channel Classes
アプリケーションがさまざまなチャネルを使用している場合、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;
}
}
Laravel の他の多くのクラスと同様に、チャネル クラスは service container によって自動的に解決されます。したがって、コンストラクターでチャネルに必要な依存関係をタイプヒントで指定できます。
Broadcasting Events
イベントを定義し、それを ShouldBroadcast インターフェイスでマークしたら、あとはイベントのディスパッチ メソッドを使用してイベントを起動するだけです。イベント ディスパッチャは、イベントが ShouldBroadcast インターフェイスでマークされていることを認識し、ブロードキャスト用にイベントをキューに入れます。
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
Only to Others
イベント ブロードキャストを利用するアプリケーションを構築する場合、現在のユーザーを除く特定のチャネルのすべての加入者にイベントをブロードキャストすることが必要になる場合があります。これは、broadcast ヘルパと toOthers メソッドを使用して実現できます。
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->toOthers();
toOthers メソッドを使用する必要がある場合をよりよく理解するために、ユーザーがタスク名を入力して新しいタスクを作成できるタスク リスト アプリケーションを想像してみましょう。タスクを作成するために、アプリケーションは、タスクの作成をブロードキャストし、新しいタスクの JSON 表現を返す /task URL にリクエストを行うことがあります。 JavaScript アプリケーションがエンドポイントから応答を受け取ると、次のように新しいタスクをタスク リストに直接挿入することがあります。
axios.post('/task', task)
.then((response) => {
this.tasks.push(response.data);
});
ただし、タスクの作成もブロードキャストすることに注意してください。タスク リストにタスクを追加するために JavaScript アプリケーションもこのイベントをリッスンしている場合、リストには重複したタスク (エンドポイントからのタスクとブロードキャストからのタスク) が 1 つずつ存在することになります。これを解決するには、toOthers メソッドを使用して、現在のユーザーにイベントをブロードキャストしないようにブロードキャスタに指示します。
toOthersメソッドを呼び出すには、イベントでIlluminate\Broadcasting\InteractsWithSockets特性を使用する必要があります。
Configuration
Laravel Echo インスタンスを初期化すると、接続にソケット ID が割り当てられます。グローバル Axios インスタンスを使用して JavaScript アプリケーションから HTTP リクエストを作成している場合、ソケット ID はすべての発信リクエストに X-Socket-ID ヘッダーとして自動的に付加されます。次に、toOthers メソッドを呼び出すと、Laravel はヘッダーからソケット ID を抽出し、そのソケット ID を持つ接続にブロードキャストしないようにブロードキャスタに指示します。
グローバル Axios インスタンスを使用していない場合は、すべての送信リクエストで X-Socket-ID ヘッダーを送信するように JavaScript アプリケーションを手動で構成する必要があります。 Echo.socketId メソッドを使用してソケット ID を取得できます。
var socketId = Echo.socketId();
Customizing the Connection
アプリケーションが複数のブロードキャスト接続と対話し、デフォルト以外のブロードキャスタを使用してイベントをブロードキャストしたい場合は、via メソッドを使用してイベントをプッシュする接続を指定できます。
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->via('pusher');
あるいは、イベントのコンストラクター内で broadcastVia メソッドを呼び出して、イベントのブロードキャスト接続を指定することもできます。ただし、これを行う前に、イベント クラスが InteractsWithBroadcasting 特性を使用していることを確認する必要があります。
<?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');
}
}
Anonymous Events
場合によっては、専用のイベント クラスを作成せずに、アプリケーションのフロントエンドに単純なイベントをブロードキャストしたい場合があります。これに対応するために、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 メソッドを使用して匿名イベントをブロードキャストすると、処理のためにイベントがアプリケーションの queue にディスパッチされます。ただし、イベントをすぐにブロードキャストしたい場合は、sendNow メソッドを使用できます。
Broadcast::on('orders.'.$order->id)->sendNow();
現在認証されているユーザーを除くすべてのチャネル加入者にイベントをブロードキャストするには、toOthers メソッドを呼び出すことができます。
Broadcast::on('orders.'.$order->id)
->toOthers()
->send();
Rescuing Broadcasts
アプリケーションのキューサーバーが利用できない場合、またはイベントのブロードキャスト中に Laravel でエラーが発生した場合、例外がスローされ、通常はエンドユーザーにアプリケーションエラーが表示されます。イベント ブロードキャストは多くの場合、アプリケーションのコア機能を補足するものであるため、イベントに ShouldRescue インターフェイスを実装することで、これらの例外によってユーザー エクスペリエンスが中断されるのを防ぐことができます。
ShouldRescue インターフェイスを実装するイベントは、ブロードキャスト試行中に Laravel の rescue helper function を自動的に利用します。このヘルパは例外をキャッチし、アプリケーションの例外ハンドラーに報告してログを記録し、ユーザーのワークフローを中断することなくアプリケーションが通常どおり実行を継続できるようにします。
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldRescue;
class ServerCreated implements ShouldBroadcast, ShouldRescue
{
// ...
}
Receiving Broadcasts
Listening for Events
installed and instantiated 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(/* ... */);
Stop Listening for Events
leaving the channel を使用せずに特定のイベントのリッスンを停止したい場合は、stopListening メソッドを使用できます。
Echo.private(`orders.${this.order.id}`)
.stopListening('OrderShipmentStatusUpdated');
Leaving a Channel
チャンネルを離れるには、Echo インスタンスで leaveChannel メソッドを呼び出します。
Echo.leaveChannel(`orders.${this.order.id}`);
チャネル、およびそれに関連付けられたプライベート チャネルおよびプレゼンス チャネルから脱退したい場合は、leave メソッドを呼び出すことができます。
Echo.leave(`orders.${this.order.id}`);
Namespaces
上記の例で、イベント クラスに完全な 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) => {
// ...
});
Using React, Vue, or Svelte
Laravel Echo には、イベントのリッスンを容易にする React、Vue、Svelte フックが含まれています。まず、プライベート イベントをリッスンするために使用される 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>
<script>
import { useEcho } from "@laravel/echo-svelte";
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>
<script>
import { useEcho } from "@laravel/echo-svelte";
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>
Connecting to Public Channels
パブリック チャネルに接続するには、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>
<script>
import { useEchoPublic } from "@laravel/echo-svelte";
useEchoPublic("posts", "PostPublished", (e) => {
console.log(e.post);
});
</script>
Connecting to Presence Channels
プレゼンス チャネルに接続するには、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>
<script>
import { useEchoPresence } from "@laravel/echo-svelte";
useEchoPresence("posts", "PostPublished", (e) => {
console.log(e.post);
});
</script>
Connection Status
useConnectionStatus フックを使用して、現在の WebSocket 接続ステータスを取得できます。これにより、接続状態が変化したときに自動的に更新されるリアクティブ ステータスが提供されます。
import { useConnectionStatus } from "@laravel/echo-react";
function ConnectionIndicator() {
const status = useConnectionStatus();
return <div>Connection: {status}</div>;
}
<script setup lang="ts">
import { useConnectionStatus } from "@laravel/echo-vue";
const status = useConnectionStatus();
</script>
<template>
<div>Connection: {{ status }}</div>
</template>
<script>
import { useConnectionStatus } from "@laravel/echo-svelte";
const status = useConnectionStatus();
</script>
<div>Connection: {status()}</div>
可能なステータス値は次のとおりです。
connected- WebSocket サーバーに正常に接続されました。connecting- 初期接続試行中です。reconnecting- 切断後に再接続を試みています。disconnected- 接続されておらず、再接続を試行していません。failed- 接続に失敗したため、再試行しません。
Socket ID
useSocketId フックを使用して、現在の WebSocket ソケット ID を取得できます。これは、新しいソケット ID で接続が再接続されたときに自動的に更新されるリアクティブな値を提供します。
import { useSocketId } from "@laravel/echo-react";
function SocketIndicator() {
const socketId = useSocketId();
return <div>Socket ID: {socketId}</div>;
}
<script setup lang="ts">
import { useSocketId } from "@laravel/echo-vue";
const socketId = useSocketId();
</script>
<template>
<div>Socket ID: {{ socketId }}</div>
</template>
<script>
import { useSocketId } from "@laravel/echo-svelte";
const socketId = useSocketId();
</script>
<div>Socket ID: {socketId()}</div>
Presence Channels
プレゼンス チャネルは、プライベート チャネルのセキュリティに基づいて構築されると同時に、誰がチャネルに登録しているかを認識する追加機能を公開します。これにより、別のユーザーが同じページを表示しているときにユーザーに通知したり、チャット ルームの住民をリストしたりするなど、強力な共同アプリケーション機能を簡単に構築できます。
Authorizing Presence Channels
すべてのプレゼンス チャネルはプライベート チャネルでもあります。したがって、ユーザーは authorized to access them である必要があります。ただし、プレゼンス チャネルの承認コールバックを定義する場合、ユーザーがチャネルへの参加を承認されている場合は、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];
}
});
Joining Presence Channels
プレゼンス チャネルに参加するには、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 の解析に問題があった場合に実行されます。
Broadcasting to Presence Channels
プレゼンス チャネルは、パブリック チャネルまたはプライベート チャネルと同様にイベントを受信できます。チャットルームの例を使用すると、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) => {
// ...
});
Model Broadcasting
モデルブロードキャストに関する以下のドキュメントを読む前に、Laravel のモデルブロードキャストサービスの一般的な概念とブロードキャストイベントを手動で作成してリッスンする方法を理解しておくことをお勧めします。
アプリケーションの Eloquent models が作成、更新、または削除されたときにイベントをブロードキャストするのが一般的です。もちろん、これは手動で defining custom events for Eloquent model state changes を実行し、それらのイベントを ShouldBroadcast インターフェイスでマークすることで簡単に実現できます。
ただし、これらのイベントをアプリケーション内の他の目的で使用していない場合、イベントをブロードキャストすることだけを目的としてイベント クラスを作成するのは面倒になる可能性があります。これを解決するために、Laravel では、Eloquent モデルが状態の変更を自動的にブロードキャストする必要があることを示すことができます。
まず、Eloquent モデルで Illuminate\Database\Eloquent\BroadcastsEvents トレイトを使用する必要があります。さらに、モデルは 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],
};
}
Customizing Model Broadcasting Event Creation
場合によっては、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();
}
Model Broadcasting Conventions
Channel Conventions
お気づきかと思いますが、上記のモデル例の broadcastOn メソッドは Channel インスタンスを返しませんでした。代わりに、Eloquent モデルが直接返されました。 Eloquent モデルインスタンスがモデルの broadcastOn メソッドによって返される (またはメソッドによって返される配列に含まれる) 場合、Laravel はモデルのクラス名と主キー識別子をチャネル名として使用して、モデルのプライベートチャネルインスタンスを自動的にインスタンス化します。
したがって、1 の id を持つ App\Models\User モデルは、App.Models.User.1 という名前の Illuminate\Broadcasting\PrivateChannel インスタンスに変換されます。もちろん、モデルの 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 メソッドを呼び出すことができます。たとえば、このメソッドは、1 の id を持つ App\Models\User モデルの文字列 App.Models.User.1 を返します。
$user->broadcastChannel();
Event Conventions
モデル ブロードキャスト イベントは、アプリケーションの App\Events ディレクトリ内の「実際の」イベントに関連付けられていないため、規則に基づいて名前とペイロードが割り当てられます。 Laravel の規則では、モデルのクラス名 (名前空間は含まない) とブロードキャストをトリガーしたモデル イベントの名前を使用してイベントをブロードキャストします。
したがって、たとえば、App\Models\Post モデルを更新すると、次のペイロードを持つ PostUpdated としてイベントがクライアント側アプリケーションにブロードキャストされます。
{
"model": {
"id": 1,
"title": "My first post"
...
},
...
"socket": "someSocketId"
}
App\Models\User モデルを削除すると、UserDeleted という名前のイベントがブロードキャストされます。
必要に応じて、broadcastAs メソッドと broadcastWith メソッドをモデルに追加することで、カスタムのブロードキャスト名とペイロードを定義できます。これらのメソッドは、発生しているモデル イベント/操作の名前を受け取り、モデル操作ごとにイベントの名前とペイロードをカスタマイズできます。 null が broadcastAs メソッドから返された場合、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],
};
}
Listening for Model Broadcasts
BroadcastsEvents 特性をモデルに追加し、モデルの broadcastOn メソッドを定義したら、クライアント側アプリケーション内でブロードキャストされたモデル イベントのリッスンを開始する準備が整います。始める前に、listening for events の完全なドキュメントを参照してください。
まず、private メソッドを使用してチャネルのインスタンスを取得し、次に listen メソッドを呼び出して指定されたイベントをリッスンします。通常、private メソッドに指定されるチャネル名は、Laravel の model broadcasting conventions に対応する必要があります。
チャネル インスタンスを取得したら、listen メソッドを使用して特定のイベントをリッスンできます。モデル ブロードキャスト イベントは、アプリケーションの App\Events ディレクトリ内の「実際の」イベントに関連付けられていないため、特定の名前空間に属していないことを示すために、event name の先頭に . を付ける必要があります。各モデルのブロードキャスト イベントには、モデルのブロードCastableなプロパティがすべて含まれる model プロパティがあります。
Echo.private(`App.Models.User.${this.user.id}`)
.listen('.UserUpdated', (e) => {
console.log(e.model);
});
Using React, Vue, or Svelte
React、Vue、または Svelte を使用している場合は、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>
<script>
import { useEchoModel } from "@laravel/echo-svelte";
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);
});
Client Events
Pusher Channels を使用する場合、クライアント イベントを送信するには、application dashboard の [アプリ設定] セクションで [クライアント イベント] オプションを有効にする必要があります。
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>
<script>
import { useEcho } from "@laravel/echo-svelte";
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>
<script>
import { useEcho } from "@laravel/echo-svelte";
const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
console.log('Chat event received:', e);
});
channel().listenForWhisper('typing', (e) => {
console.log(e.name);
});
</script>
Notifications
イベント ブロードキャストと notifications を組み合わせることにより、JavaScript アプリケーションは、ページを更新しなくても、新しい通知が発生したときに受信できるようになります。始める前に、the broadcast notification channel の使用に関するドキュメントを必ずお読みください。
ブロードキャスト チャネルを使用するように通知を構成したら、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>
<script>
import { useEchoModel } from "@laravel/echo-svelte";
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 ファイルに含まれています。
Stop Listening for Notifications
leaving the channel を使用せずに通知のリスニングを停止したい場合は、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);