ブロードキャスト
- イントロダクション
- サーバーサイドのインストール
- クライアントサイドのインストール
- 概念の概要
- ブロードキャストイベントの定義
- チャネルの承認
- イベントのブロードキャスト
- ブロードキャストの受信
- プレゼンスチャネル
- モデルブロードキャスト
- クライアントイベント
- 通知
イントロダクション
多くの最新のWebアプリケーションでは、WebSocketsを使用して、リアルタイムのライブ更新ユーザーインターフェイスを実装しています。サーバー上のデータが更新されると、メッセージは通常WebSocket接続を介して送信され、クライアントによって処理されます。 WebSocketsは、UIに反映されるべきデータの変更をアプリケーションのサーバーに継続的にポーリングするよりも効率的な代替手段を提供します。
たとえば、アプリケーションがユーザーのデータをCSVファイルにエクスポートしてメールで送信できるとします。ただし、このCSVファイルの作成には数分かかるため、キューに入れられたジョブ内でCSVを作成してメールで送信することを選択します。 CSVが作成され、ユーザーにメールで送信されると、イベントブロードキャストを使用して、アプリケーションのJavaScriptが受信するApp\Events\UserDataExported
イベントをディスパッチできます。イベントが受信されると、ページを更新する必要なく、CSVがメールで送信されたことをユーザーにメッセージを表示できます。
この種の機能の構築を支援するために、LaravelはサーバーサイドのLaravel イベントをWebSocket接続を介して「ブロードキャスト」することを容易にします。Laravelイベントをブロードキャストすることで、サーバーサイドのLaravelアプリケーションとクライアントサイドのJavaScriptアプリケーション間で同じイベント名とデータを共有できます。
ブロードキャストの背後にある中心的な概念はシンプルです。クライアントはフロントエンドの名前付きチャネルに接続し、Laravelアプリケーションはバックエンドでこれらのチャネルにイベントをブロードキャストします。これらのイベントには、フロントエンドで利用できるようにしたい追加データを含めることができます。
サポートされているドライバ
デフォルトでは、Laravelには、Laravel Reverb、Pusher Channels、Ablyの3つのサーバーサイドブロードキャストドライバが含まれています。
イベントブロードキャストに進む前に、イベントとリスナーに関するLaravelのドキュメントをお読みください。
サーバーサイドのインストール
Laravelのイベントブロードキャストの使用を開始するには、Laravelアプリケーション内でいくつかの設定を行うとともに、いくつかのパッケージをインストールする必要があります。
イベントブロードキャストは、Laravel Echo(JavaScriptライブラリ)がブラウザクライアント内で受信できるように、Laravelイベントをブロードキャストするサーバーサイドブロードキャストドライバによって実現されます。心配しないでください。インストールプロセスの各パートをステップバイステップで説明します。
設定
アプリケーションのすべてのイベントブロードキャスト設定は、`config/broadcasting.php`設定ファイルに保存されます。このディレクトリがアプリケーションに存在しない場合でも心配しないでください。 `install:broadcasting` Artisanコマンドを実行すると作成されます。
Laravelは、Laravel Reverb、Pusher Channels、Ably、およびローカル開発とデバッグ用の`log`ドライバなど、すぐに使用できる複数のブロードキャストドライバをサポートしています。さらに、テスト中にブロードキャストを無効にすることができる`null`ドライバも含まれています。 `config/broadcasting.php`設定ファイルには、これらの各ドライバの設定例が含まれています。
インストール
デフォルトでは、新しいLaravelアプリケーションではブロードキャストは有効になっていません。 `install:broadcasting` Artisanコマンドを使用してブロードキャストを有効にできます
php artisan install:broadcasting
`install:broadcasting`コマンドは、`config/broadcasting.php`設定ファイルを作成します。さらに、コマンドは、アプリケーションのブロードキャスト承認ルートとコールバックを登録できる`routes/channels.php`ファイルを作成します。
キューの設定
イベントをブロードキャストする前に、最初にキューワーカーを設定して実行する必要があります。すべてのイベントブロードキャストは、キューに入れられたジョブを介して行われるため、アプリケーションの応答時間は、ブロードキャストされるイベントによって深刻な影響を受けません。
Reverb
`install:broadcasting`コマンドを実行すると、Laravel Reverbをインストールするように求められます。もちろん、Composerパッケージマネージャーを使用してReverbを手動でインストールすることもできます。
composer require laravel/reverb
パッケージがインストールされたら、Reverbのインストールコマンドを実行して、設定を公開し、Reverbに必要な環境変数を追加し、アプリケーションでイベントブロードキャストを有効にできます
php artisan reverb:install
Reverbのインストールと使用方法の詳細な手順は、Reverbのドキュメントにあります。
Pusher Channels
Pusher Channelsを使用してイベントをブロードキャストする場合は、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=443PUSHER_SCHEME="https"PUSHER_APP_CLUSTER="mt1"
`config/broadcasting.php`ファイルの`pusher`設定では、クラスターなど、チャネルでサポートされている追加の`options`を指定することもできます。
次に、アプリケーションの`.env`ファイルで`BROADCAST_CONNECTION`環境変数を`pusher`に設定します
BROADCAST_CONNECTION=pusher
最後に、クライアントサイドでブロードキャストイベントを受信するLaravel Echoをインストールして設定する準備ができました。
Ably
以下のドキュメントでは、「Pusher互換」モードでAblyを使用する方法について説明しています。ただし、Ablyチームは、Ablyが提供する独自の機能を活用できるブロードキャスターとEchoクライアントを推奨および保守しています。 Ablyが保守するドライバの使用の詳細については、AblyのLaravelブロードキャスターのドキュメントを参照してください。
Ablyを使用してイベントをブロードキャストする場合は、Composerパッケージマネージャーを使用してAbly PHP SDKをインストールする必要があります
composer require ably/ably-php
次に、`config/broadcasting.php` 設定ファイルで Ably 認証情報を設定する必要があります。このファイルには Ably 設定の例が既に含まれており、キーをすばやく指定できます。通常、この値は `ABLY_KEY` 環境変数 を介して設定する必要があります。
ABLY_KEY=your-ably-key
次に、アプリケーションの `.env` ファイルで `BROADCAST_CONNECTION` 環境変数を `ably` に設定します。
BROADCAST_CONNECTION=ably
最後に、クライアントサイドでブロードキャストイベントを受信するLaravel Echoをインストールして設定する準備ができました。
クライアントサイドのインストール
Reverb
Laravel Echo は、チャンネルを購読し、サーバーサイドのブロードキャストドライバーによってブロードキャストされたイベントをリッスンすることを容易にする JavaScript ライブラリです。Echo は NPM パッケージマネージャーを介してインストールできます。この例では、Reverb が WebSocket の購読、チャンネル、およびメッセージに Pusher プロトコルを使用するため、`pusher-js` パッケージもインストールします。
npm install --save-dev laravel-echo pusher-js
Echo をインストールしたら、アプリケーションの JavaScript で新しい Echo インスタンスを作成する準備ができました。これを行うのに最適な場所は、Laravel フレームワークに含まれている `resources/js/bootstrap.js` ファイルの下部です。デフォルトでは、このファイルには Echo 設定の例が既に含まれています。コメントを外して、`broadcaster` 設定オプションを `reverb` に更新するだけです。
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, 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 ライブラリです。Echo は、WebSocket の購読、チャンネル、およびメッセージに Pusher プロトコルを実装するために、`pusher-js` NPM パッケージも活用します。
`install:broadcasting` Artisan コマンドは、`laravel-echo` および `pusher-js` パッケージを自動的にインストールします。ただし、これらのパッケージは NPM を介して手動でインストールすることもできます。
npm install --save-dev laravel-echo pusher-js
Echo をインストールしたら、アプリケーションの JavaScript で新しい Echo インスタンスを作成する準備ができました。`install:broadcasting` コマンドは、`resources/js/echo.js` に Echo 設定ファイルを作成します。ただし、このファイルのデフォルト設定は Laravel Reverb 用です。以下の設定をコピーして、設定を Pusher に移行できます。
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});
次に、アプリケーションの `.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=443PUSHER_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 に関するドキュメントを参照してください。
既存のクライアントインスタンスの使用
Echo に使用させたい、事前に設定された Pusher Channels クライアントインスタンスが既にある場合は、`client` 設定オプションを介して Echo に渡すことができます。
import Echo from 'laravel-echo';import Pusher from 'pusher-js'; const options = { broadcaster: 'pusher', key: 'your-pusher-channels-key'} window.Echo = new Echo({ ...options, client: new Pusher(options.key, options)});
Ably
以下のドキュメントでは、「Pusher互換」モードでAblyを使用する方法について説明しています。ただし、Ablyチームは、Ablyが提供する独自の機能を活用できるブロードキャスターとEchoクライアントを推奨および保守しています。 Ablyが保守するドライバの使用の詳細については、AblyのLaravelブロードキャスターのドキュメントを参照してください。
Laravel Echo は、チャンネルを購読し、サーバーサイドのブロードキャストドライバーによってブロードキャストされたイベントをリッスンすることを容易にする JavaScript ライブラリです。Echo は、WebSocket の購読、チャンネル、およびメッセージに Pusher プロトコルを実装するために、`pusher-js` NPM パッケージも活用します。
`install:broadcasting` Artisan コマンドは、`laravel-echo` および `pusher-js` パッケージを自動的にインストールします。ただし、これらのパッケージは NPM を介して手動でインストールすることもできます。
npm install --save-dev laravel-echo pusher-js
続行する前に、Ably アプリケーション設定で Pusher プロトコルのサポートを有効にする必要があります。この機能は、Ably アプリケーションの設定ダッシュボードの「プロトコルアダプター設定」セクションで有効にできます。
Echo をインストールしたら、アプリケーションの JavaScript で新しい Echo インスタンスを作成する準備ができました。`install:broadcasting` コマンドは、`resources/js/echo.js` に Echo 設定ファイルを作成します。ただし、このファイルのデフォルト設定は Laravel Reverb 用です。以下の設定をコピーして、設定を Ably に移行できます。
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,});
Ably Echo 設定が `VITE_ABLY_PUBLIC_KEY` 環境変数を参照していることに気付いたかもしれません。この変数の値は、Ably 公開キーである必要があります。公開キーは、Ably キーの `:` 文字より前の部分です。
ニーズに合わせて Echo 設定を調整したら、アプリケーションのアセットをコンパイルできます。
npm run dev
アプリケーションの JavaScript アセットのコンパイルの詳細については、Vite に関するドキュメントを参照してください。
概念の概要
Laravel のイベントブロードキャストを使用すると、WebSockets へのドライバーベースのアプローチを使用して、サーバーサイドの Laravel イベントをクライアントサイドの JavaScript アプリケーションにブロードキャストできます。現在、Laravel には Pusher Channels と Ably ドライバーが付属しています。イベントは、Laravel Echo JavaScript パッケージを使用して、クライアントサイドで簡単に使用できます。
イベントは「チャンネル」を介してブロードキャストされ、パブリックまたはプライベートとして指定できます。アプリケーションへの訪問者は、認証や承認なしでパブリックチャンネルを購読できます。ただし、プライベートチャンネルを購読するには、ユーザーが認証され、そのチャンネルをリッスンする権限を持っている必要があります。
サンプルアプリケーションの使用
イベントブロードキャストの各コンポーネントを詳しく説明する前に、eコマースストアを例に使用して概要を説明します。
アプリケーションでは、ユーザーが注文の配送状況を表示できるページがあるとします。また、配送状況の更新がアプリケーションによって処理されると、`OrderShipmentStatusUpdated` イベントが発生するとします。
use App\Events\OrderShipmentStatusUpdated; OrderShipmentStatusUpdated::dispatch($order);
`ShouldBroadcast` インターフェース
ユーザーが注文の 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), // ... ];}
チャネルの承認
ユーザーはプライベートチャンネルをリッスンする権限を持っている必要があることに注意してください。チャンネル承認ルールは、アプリケーションの `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` メソッドは、2 つの引数を受け取ります。チャンネルの名前と、ユーザーがチャンネルをリッスンする権限を持っているかどうかを示す `true` または `false` を返すコールバックです。
すべての承認コールバックは、最初の引数として現在認証されているユーザーを受け取り、後続の引数として追加のワイルドカードパラメーターを受け取ります。この例では、`{orderId}` プレースホルダーを使用して、チャンネル名の「ID」部分がワイルドカードであることを示しています。
イベントブロードキャストのリッスン
次に、JavaScript アプリケーションでイベントをリッスンするだけです。Laravel Echo を使用してこれを行うことができます。最初に、`private` メソッドを使用してプライベートチャンネルを購読します。次に、`listen` メソッドを使用して `OrderShipmentStatusUpdated` イベントをリッスンできます。デフォルトでは、すべてのイベントのパブリックプロパティがブロードキャストイベントに含まれます。
Echo.private(`orders.${orderId}`) .listen('OrderShipmentStatusUpdated', (e) => { console.log(e.order); });
ブロードキャストイベントの定義
特定のイベントをブロードキャストする必要があることを Laravel に通知するには、イベントクラスで `Illuminate\Contracts\Broadcasting\ShouldBroadcast` インターフェースを実装する必要があります。このインターフェースは、フレームワークによって生成されたすべてのイベントクラスに既にインポートされているため、イベントに簡単に追加できます。
`ShouldBroadcast` インターフェースでは、`broadcastOn` という 1 つのメソッドを実装する必要があります。`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 アプリケーションからパブリックデータにアクセスできます。たとえば、イベントに 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];}
ブロードキャストキュー
デフォルトでは、各ブロードキャストイベントは、`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` キューを使用してイベントをブロードキャストする場合は、`ShouldBroadcast` の代わりに `ShouldBroadcastNow` インターフェースを実装できます。
<?php use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; class OrderShipmentStatusUpdated implements ShouldBroadcastNow{ // ...}
ブロードキャスト条件
特定の条件が true の場合にのみイベントをブロードキャストしたい場合があります。これらの条件は、イベントクラスに `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
ルートを自動的に登録します。/broadcasting/auth
ルートは、自動的にweb
ミドルウェアグループ内に配置されます。
承認コールバックの定義
次に、現在認証されているユーザーが特定のチャンネルをリッスンできるかどうかを実際に判断するロジックを定義する必要があります。これは、install:broadcasting
Artisanコマンドによって作成されたroutes/channels.php
ファイルで行います。このファイルでは、Broadcast::channel
メソッドを使用して、チャンネル承認コールバックを登録できます。
use App\Models\User; Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) { return $user->id === Order::findOrNew($orderId)->user_id;});
`channel` メソッドは、2 つの引数を受け取ります。チャンネルの名前と、ユーザーがチャンネルをリッスンする権限を持っているかどうかを示す `true` または `false` を返すコールバックです。
すべての承認コールバックは、最初の引数として現在認証されているユーザーを受け取り、後続の引数として追加のワイルドカードパラメーターを受け取ります。この例では、`{orderId}` プレースホルダーを使用して、チャンネル名の「ID」部分がワイルドカードであることを示しています。
channel:list
Artisanコマンドを使用して、アプリケーションのブロードキャスト承認コールバックのリストを表示できます。
php artisan channel:list
承認コールバックのモデルバインディング
HTTPルートと同様に、チャンネルルートも暗黙的および明示的なルートモデルバインディングを利用できます。たとえば、文字列または数値の注文IDを受け取る代わりに、実際のOrder
モデルインスタンスを要求できます。
use App\Models\Order;use App\Models\User; Broadcast::channel('orders.{order}', function (User $user, Order $order) { return $user->id === $order->user_id;});
HTTPルートモデルバインディングとは異なり、チャンネルモデルバインディングは自動暗黙的モデルバインディングスコープをサポートしていません。ただし、ほとんどのチャンネルは単一のモデルの一意のプライマリキーに基づいてスコープを設定できるため、これはめったに問題になりません。
承認コールバックの認証
プライベートおよびプレゼンスブロードキャストチャンネルは、アプリケーションのデフォルト認証ガードを介して現在のユーザーを認証します。ユーザーが認証されていない場合、チャンネルの承認は自動的に拒否され、承認コールバックは実行されません。ただし、必要に応じて受信リクエストを認証する必要がある複数のカスタムガードを割り当てることができます。
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; }}
Laravelの他の多くのクラスと同様に、チャンネルクラスはサービスコンテナによって自動的に解決されます。そのため、コンストラクターでチャンネルに必要な依存関係をタイプヒントで指定できます。
イベントのブロードキャスト
イベントを定義し、ShouldBroadcast
インターフェースでマークしたら、イベントのディスパッチメソッドを使用してイベントを発生させるだけです。イベントディスパッチャーは、イベントが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アプリケーションがこのイベントもリッスンしてタスクをタスクリストに追加する場合、リストには重複するタスクがあります。1つはエンドポイントから、もう1つはブロードキャストからです。これは、toOthers
メソッドを使用して、ブロードキャスターに現在のユーザーにイベントをブロードキャストしないように指示することで解決できます。
toOthers
メソッドを呼び出すには、イベントでIlluminate\Broadcasting\InteractsWithSockets
トレイトを使用する必要があります。
設定
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();
接続のカスタマイズ
アプリケーションが複数のブロードキャスト接続と対話していて、デフォルト以外のブロードキャスターを使用してイベントをブロードキャストする場合、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'); }}
匿名イベント
専用のイベントクラスを作成せずに、アプリケーションのフロントエンドに単純なイベントをブロードキャストしたい場合があります。これに対応するために、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 Echoをインストールしてインスタンス化したら、Laravelアプリケーションからブロードキャストされるイベントのリッスンを開始する準備ができました。まず、channel
メソッドを使用してチャンネルのインスタンスを取得し、次にlisten
メソッドを呼び出して指定されたイベントをリッスンします。
Echo.channel(`orders.${this.order.id}`) .listen('OrderShipmentStatusUpdated', (e) => { console.log(e.order.name); });
プライベートチャンネルのイベントをリッスンする場合は、代わりにprivate
メソッドを使用します。単一のチャンネルで複数のイベントをリッスンするために、listen
メソッドへの呼び出しをチェーンし続けることができます。
Echo.private(`orders.${this.order.id}`) .listen(/* ... */) .listen(/* ... */) .listen(/* ... */);
イベントのリッスンを停止する
チャンネルを離れることなく特定のイベントのリスニングを停止する場合は、stopListening
メソッドを使用できます。
Echo.private(`orders.${this.order.id}`) .stopListening('OrderShipmentStatusUpdated')
チャネルの退出
チャンネルを離れるには、EchoインスタンスでleaveChannel
メソッドを呼び出すことができます。
Echo.leaveChannel(`orders.${this.order.id}`);
チャンネルとそれに関連付けられたプライベートおよびプレゼンスチャンネルも離れる場合は、leave
メソッドを呼び出すことができます。
Echo.leave(`orders.${this.order.id}`);
名前空間
上記の例では、イベントクラスの完全なApp\Events
名前空間を指定していないことに気付いたかもしれません。これは、EchoがイベントがApp\Events
名前空間にあると自動的に想定するためです。ただし、namespace
設定オプションを渡すことで、Echoをインスタンス化するときにルート名前空間を設定できます。
window.Echo = new Echo({ broadcaster: 'pusher', // ... namespace: 'App.Other.Namespace'});
または、Echoを使用してサブスクライブするときに、イベントクラスの前に.
を付けることができます。これにより、常に完全修飾クラス名を指定できます。
Echo.channel('orders') .listen('.Namespace\\Event\\Class', (e) => { // ... });
プレゼンスチャネル
プレゼンスチャンネルは、プライベートチャンネルのセキュリティに基づいて構築されており、チャンネルに登録しているユーザーを認識できるという追加機能を提供します。これにより、別のユーザーが同じページを閲覧しているときにユーザーに通知したり、チャットルームの参加者を一覧表示したりするなど、強力な共同アプリケーション機能を簡単に構築できます。
プレゼンスチャネルの承認
すべてのプレゼンスチャンネルはプライベートチャンネルでもあります。したがって、ユーザーはアクセスを承認される必要があります。ただし、プレゼンスチャンネルの承認コールバックを定義する場合、ユーザーがチャンネルに参加することを承認されている場合は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
メソッドは、listen
メソッドを公開するだけでなく、here
、joining
、およびleaving
イベントにサブスクライブできるPresenceChannel
実装を返します。
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) => { // ... });
モデルブロードキャスト
モデルブロードキャストに関する以下のドキュメントを読む前に、Laravelのモデルブロードキャストサービスの一般的な概念と、ブロードキャストイベントを手動で作成およびリッスンする方法について理解しておくことをお勧めします。
アプリケーションのEloquentモデルが作成、更新、または削除されたときにイベントをブロードキャストするのが一般的です。もちろん、これはEloquentモデルの状態変更のカスタムイベントを手動で定義し、それらのイベントに`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], };}
モデルブロードキャストイベントの作成のカスタマイズ
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はモデルのクラス名とプライマリキー識別子をチャネル名として使用して、モデルのプライベートチャネルインスタンスを自動的にインスタンス化します。
そのため、id
が1
の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
メソッドを呼び出すことができます。たとえば、このメソッドは、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
トレイトを追加し、モデルのbroadcastOn
メソッドを定義したら、クライアントサイドアプリケーション内でブロードキャストされたモデルイベントのリッスンを開始する準備ができました。開始する前に、イベントのリッスンに関する完全なドキュメントを参照することをお勧めします。
まず、private
メソッドを使用してチャネルのインスタンスを取得し、次にlisten
メソッドを呼び出して指定されたイベントをリッスンします。通常、private
メソッドに指定されるチャネル名は、Laravelのモデルブロードキャスト規約に対応している必要があります。
チャネルインスタンスを取得したら、listen
メソッドを使用して特定のイベントをリッスンできます。モデルブロードキャストイベントは、アプリケーションのApp\Events
ディレクトリ内の「実際の」イベントに関連付けられていないため、イベント名の先頭に.
を付けて、特定の名前に属さないことを示す必要があります空間。各モデルブロードキャストイベントには、モデルのブロードキャスト可能なすべてのプロパティを含むmodel
プロパティがあります。
Echo.private(`App.Models.User.${this.user.id}`) .listen('.PostUpdated', (e) => { console.log(e.model); });
クライアントイベント
Pusher Channelsを使用する場合、クライアントイベントを送信するには、アプリケーションダッシュボードの「アプリ設定」セクションで「クライアントイベント」オプションを有効にする必要があります。
Laravelアプリケーションにまったくアクセスせずに、接続されている他のクライアントにイベントをブロードキャストしたい場合があります。これは、特定の画面で別のユーザーがメッセージを入力していることをアプリケーションのユーザーに警告したい「入力中」通知などに特に役立ちます。
クライアントイベントをブロードキャストするには、Echoのwhisper
メソッドを使用できます。
Echo.private(`chat.${roomId}`) .whisper('typing', { name: this.user.name });
クライアントイベントをリッスンするには、listenForWhisper
メソッドを使用できます。
Echo.private(`chat.${roomId}`) .listenForWhisper('typing', (e) => { console.log(e.name); });
通知
イベントブロードキャストと通知を組み合わせることで、JavaScriptアプリケーションはページを更新することなく、新しい通知が発生したときに受信できます。開始する前に、ブロードキャスト通知チャネルの使用に関するドキュメントをよく読んでください。
ブロードキャストチャネルを使用するように通知を構成したら、Echoのnotification
メソッドを使用してブロードキャストイベントをリッスンできます。チャネル名は、通知を受信するエンティティのクラス名と一致する必要があることに覚えておいてください。
Echo.private(`App.Models.User.${userId}`) .notification((notification) => { console.log(notification.type); });
この例では、broadcast
チャネルを介してApp\Models\User
インスタンスに送信されたすべての通知がコールバックによって受信されます。 App.Models.User.{id}
チャネルのチャネル認証コールバックは、アプリケーションのroutes/channels.php
ファイルに含まれています。