コンテンツにスキップ

ブロードキャスト

イントロダクション

多くの最新のWebアプリケーションでは、WebSocketsを使用して、リアルタイムのライブ更新ユーザーインターフェイスを実装しています。サーバー上のデータが更新されると、メッセージは通常WebSocket接続を介して送信され、クライアントによって処理されます。 WebSocketsは、UIに反映されるべきデータの変更をアプリケーションのサーバーに継続的にポーリングするよりも効率的な代替手段を提供します。

たとえば、アプリケーションがユーザーのデータをCSVファイルにエクスポートしてメールで送信できるとします。ただし、このCSVファイルの作成には数分かかるため、キューに入れられたジョブ内でCSVを作成してメールで送信することを選択します。 CSVが作成され、ユーザーにメールで送信されると、イベントブロードキャストを使用して、アプリケーションのJavaScriptが受信するApp\Events\UserDataExportedイベントをディスパッチできます。イベントが受信されると、ページを更新する必要なく、CSVがメールで送信されたことをユーザーにメッセージを表示できます。

この種の機能の構築を支援するために、LaravelはサーバーサイドのLaravel イベントをWebSocket接続を介して「ブロードキャスト」することを容易にします。Laravelイベントをブロードキャストすることで、サーバーサイドのLaravelアプリケーションとクライアントサイドのJavaScriptアプリケーション間で同じイベント名とデータを共有できます。

ブロードキャストの背後にある中心的な概念はシンプルです。クライアントはフロントエンドの名前付きチャネルに接続し、Laravelアプリケーションはバックエンドでこれらのチャネルにイベントをブロードキャストします。これらのイベントには、フロントエンドで利用できるようにしたい追加データを含めることができます。

サポートされているドライバ

デフォルトでは、Laravelには、Laravel ReverbPusher ChannelsAblyの3つのサーバーサイドブロードキャストドライバが含まれています。

lightbulb

イベントブロードキャストに進む前に、イベントとリスナーに関するLaravelのドキュメントをお読みください。

サーバーサイドのインストール

Laravelのイベントブロードキャストの使用を開始するには、Laravelアプリケーション内でいくつかの設定を行うとともに、いくつかのパッケージをインストールする必要があります。

イベントブロードキャストは、Laravel Echo(JavaScriptライブラリ)がブラウザクライアント内で受信できるように、Laravelイベントをブロードキャストするサーバーサイドブロードキャストドライバによって実現されます。心配しないでください。インストールプロセスの各パートをステップバイステップで説明します。

設定

アプリケーションのすべてのイベントブロードキャスト設定は、`config/broadcasting.php`設定ファイルに保存されます。このディレクトリがアプリケーションに存在しない場合でも心配しないでください。 `install:broadcasting` Artisanコマンドを実行すると作成されます。

Laravelは、Laravel ReverbPusher ChannelsAbly、およびローカル開発とデバッグ用の`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=443
PUSHER_SCHEME="https"
PUSHER_APP_CLUSTER="mt1"

`config/broadcasting.php`ファイルの`pusher`設定では、クラスターなど、チャネルでサポートされている追加の`options`を指定することもできます。

次に、アプリケーションの`.env`ファイルで`BROADCAST_CONNECTION`環境変数を`pusher`に設定します

BROADCAST_CONNECTION=pusher

最後に、クライアントサイドでブロードキャストイベントを受信するLaravel Echoをインストールして設定する準備ができました。

Ably

lightbulb

以下のドキュメントでは、「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
exclamation

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=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
lightbulb

アプリケーションの 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

lightbulb

以下のドキュメントでは、「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
lightbulb

アプリケーションの JavaScript アセットのコンパイルの詳細については、Vite に関するドキュメントを参照してください。

概念の概要

Laravel のイベントブロードキャストを使用すると、WebSockets へのドライバーベースのアプローチを使用して、サーバーサイドの Laravel イベントをクライアントサイドの JavaScript アプリケーションにブロードキャストできます。現在、Laravel には Pusher ChannelsAbly ドライバーが付属しています。イベントは、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;
}
lightbulb

これらの問題の回避策の詳細については、キューに入れられたジョブとデータベーストランザクション に関するドキュメントを参照してください。

チャネルの承認

プライベートチャンネルでは、現在認証されているユーザーが実際にチャンネルをリッスンできることを承認する必要があります。これは、チャンネル名を使用して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;
});
exclamation

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;
}
}
lightbulb

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メソッドを使用して、ブロードキャスターに現在のユーザーにイベントをブロードキャストしないように指示することで解決できます。

exclamation

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メソッドを公開するだけでなく、herejoining、および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) => {
// ...
});

モデルブロードキャスト

exclamation

モデルブロードキャストに関する以下のドキュメントを読む前に、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引数を受け取ることに気づいたかもしれません。この引数には、モデルで発生したイベントのタイプが含まれており、createdupdateddeletedtrashed、または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はモデルのクラス名とプライマリキー識別子をチャネル名として使用して、モデルのプライベートチャネルインスタンスを自動的にインスタンス化します。

そのため、id1App\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メソッドを呼び出すことができます。たとえば、このメソッドは、id1App\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);
});

クライアントイベント

lightbulb

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ファイルに含まれています。