Introduction
多くの現代のウェブアプリケーションでは、WebSocketを使用してリアルタイムでライブ更新されるユーザーインターフェースを実装しています。サーバー上のデータが更新されると、通常、WebSocket接続を介してクライアントが処理するためのメッセージが送信されます。WebSocketは、アプリケーションのサーバーに対してデータの変更を継続的にポーリングするよりも、より効率的な代替手段を提供します。
たとえば、アプリケーションがユーザーのデータをCSVファイルにエクスポートし、それをメールで送信できるとしましょう。しかし、このCSVファイルの作成には数分かかるため、キューに入れたジョブ内でCSVを作成してメールを送信することにします。CSVが作成され、ユーザーにメールが送信されると、イベントブロードキャスティングを使用して、アプリケーションのJavaScriptによって受信されるApp\Events\UserDataExported
イベントを送信できます。イベントが受信されると、ユーザーに対してCSVがメールで送信されたことを表示できます。ページをリフレッシュする必要はありません。
このような機能を構築するのを助けるために、LaravelはサーバーサイドのLaravel イベントをWebSocket接続を介して「ブロードキャスト」するのを簡単にします。Laravelイベントをブロードキャストすることで、サーバーサイドのLaravelアプリケーションとクライアントサイドのJavaScriptアプリケーションの間で同じイベント名とデータを共有できます。
ブロードキャスティングの基本概念はシンプルです:クライアントはフロントエンドの名前付きチャネルに接続し、Laravelアプリケーションはバックエンドでこれらのチャネルにイベントをブロードキャストします。これらのイベントには、フロントエンドで利用可能にしたい追加のデータを含めることができます。
Supported Drivers
デフォルトでは、Laravelには選択できる3つのサーバーサイドブロードキャスティングドライバーが含まれています:Laravel Reverb、Pusher Channels、およびAbly。
イベントブロードキャスティングに入る前に、Laravelのイベントとリスナーに関するドキュメントを読んでおくことをお勧めします。
Server Side Installation
Laravelのイベントブロードキャスティングを使用するには、Laravelアプリケーション内でいくつかの設定を行い、いくつかのパッケージをインストールする必要があります。
イベントブロードキャスティングは、Laravelイベントをブロードキャストし、Laravel Echo(JavaScriptライブラリ)がブラウザクライアント内で受信できるようにするサーバーサイドブロードキャスティングドライバーによって実現されます。心配しないでください - インストールプロセスの各部分をステップバイステップで説明します。
Configuration
アプリケーションのすべてのイベントブロードキャスティング設定は、config/broadcasting.php
設定ファイルに保存されます。このディレクトリがアプリケーションに存在しない場合でも心配しないでください。install:broadcasting
Artisanコマンドを実行すると作成されます。
Laravelは、Laravel Reverb、Pusher Channels、Ably、およびローカル開発とデバッグ用のlog
ドライバーなど、いくつかのブロードキャストドライバーを標準でサポートしています。さらに、テスト中にブロードキャストを無効にすることができるnull
ドライバーも含まれています。これらのドライバーの各設定例は、config/broadcasting.php
設定ファイルに含まれています。
Installation
デフォルトでは、新しいLaravelアプリケーションではブロードキャスティングは有効になっていません。install:broadcasting
Artisanコマンドを使用してブロードキャスティングを有効にできます:
php artisan install:broadcasting
<a name="queue-configuration"></a>
#### Queue Configuration
イベントをブロードキャストする前に、最初に[キュー作業者](/read/laravel-11-x/96fa7ac142293640.md)を設定して実行する必要があります。すべてのイベントブロードキャスティングはキューに入れられたジョブを介して行われるため、アプリケーションの応答時間がブロードキャストされるイベントによって深刻に影響を受けることはありません。
<a name="reverb"></a>
### Reverb
`````install:broadcasting`````コマンドを実行すると、[Laravel Reverb](/read/laravel-11-x/14372a38994562cc.md)をインストールするように求められます。もちろん、Composerパッケージマネージャーを使用して手動でReverbをインストールすることもできます。
``````sh
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の資格情報を設定する必要があります。このファイルには、キー、シークレット、およびアプリケーションIDをすぐに指定できるように、Pusher Channelsの設定例がすでに含まれています。通常、.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"
次に、`````BROADCAST_CONNECTION`````環境変数を`````pusher`````に設定します。アプリケーションの`````.env`````ファイルで:
``````ini
BROADCAST_CONNECTION=pusher
`
最後に、クライアント側でブロードキャストイベントを受信するLaravel Echoをインストールして設定する準備が整いました。
Ably
以下のドキュメントでは、Ablyを「Pusher互換」モードで使用する方法について説明します。ただし、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
次に、BROADCAST_CONNECTION
環境変数をably
に設定します。アプリケーションの.env
ファイルで:
BROADCAST_CONNECTION=ably
最後に、クライアント側でブロードキャストイベントを受信するLaravel Echoをインストールして設定する準備が整いました。
Client Side Installation
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=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
すでに事前に設定されたPusher Channelsクライアントインスタンスがあり、Echoに利用させたい場合は、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
以下のドキュメントでは、Ablyを「Pusher互換」モードで使用する方法について説明します。ただし、Ablyチームは、Ablyが提供するユニークな機能を活用できるブロードキャスターとEchoクライアントを推奨し、維持しています。Ablyが維持するドライバーの使用に関する詳細については、AblyのLaravelブロードキャスターのドキュメントを参照してください。
Laravel Echoは、チャネルにサブスクライブし、サーバーサイドのブロードキャスティングドライバーによってブロードキャストされたイベントをリッスンするのを簡単にするJavaScriptライブラリです。Echoはまた、WebSocketのサブスクリプション、チャネル、およびメッセージのために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キーの部分です。
設定を調整したら、アプリケーションのアセットをコンパイルできます:
npm run dev
アプリケーションのJavaScriptアセットをコンパイルする方法の詳細については、Viteに関するドキュメントを参照してください。
Concept Overview
Laravelのイベントブロードキャスティングを使用すると、サーバーサイドのLaravelイベントをクライアントサイドのJavaScriptアプリケーションにブロードキャストできます。これは、WebSocketに対するドライバーベースのアプローチを使用します。現在、LaravelはPusher ChannelsおよびAblyドライバーを提供しています。イベントは、Laravel Echo JavaScriptパッケージを使用してクライアント側で簡単に消費できます。
イベントは「チャネル」を介してブロードキャストされ、これらは公開またはプライベートとして指定できます。アプリケーションの訪問者は、認証や承認なしに公開チャネルにサブスクライブできますが、プライベートチャネルにサブスクライブするには、ユーザーが認証され、チャネルでリッスンする権限が必要です。
Using an Example Application
イベントブロードキャスティングの各コンポーネントに入る前に、eコマースストアを例にして高レベルの概要を見てみましょう。
アプリケーションには、ユーザーが注文の配送状況を確認できるページがあると仮定しましょう。また、配送状況の更新がアプリケーションによって処理されるときに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;
}
``````php
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;
});
すべての承認コールバックは、現在認証されているユーザーを最初の引数として受け取り、追加のワイルドカードパラメータをその後の引数として受け取ります。この例では、`````{orderId}`````プレースホルダーを使用して、チャネル名の「ID」部分がワイルドカードであることを示しています。
<a name="listening-for-event-broadcasts"></a>
#### Listening for Event Broadcasts
次に、JavaScriptアプリケーションでイベントをリッスンするだけです。これを[Laravel Echo](#client-side-installation)を使用して行うことができます。最初に、`````private`````メソッドを使用してプライベートチャネルにサブスクライブします。次に、`````listen`````メソッドを使用して`````OrderShipmentStatusUpdated`````イベントをリッスンできます。デフォルトでは、イベントのすべての公開プロパティがブロードキャストイベントに含まれます:
``````js
Echo.private(`orders.${orderId}`)
.listen('OrderShipmentStatusUpdated', (e) => {
console.log(e.order);
});
`
Defining Broadcast Events
Laravelに特定のイベントをブロードキャストする必要があることを通知するには、イベントクラスでIlluminate\Contracts\Broadcasting\ShouldBroadcast
インターフェースを実装する必要があります。このインターフェースは、フレームワークによって生成されたすべてのイベントクラスにすでにインポートされているため、簡単にイベントに追加できます。
``````php
<?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),
];
}
}
`
<a name="broadcast-name"></a>
### Broadcast Name
デフォルトでは、Laravelはイベントのクラス名を使用してイベントをブロードキャストします。ただし、イベントに`````broadcastAs`````メソッドを定義することで、ブロードキャスト名をカスタマイズできます:
``````php
/**
* The event's broadcast name.
*/
public function broadcastAs(): string
{
return 'server.created';
}
`
``````php
.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
プロパティを定義します:
/**
* The name of the queue connection to use when broadcasting the event.
*
* @var string
*/
public $connection = 'redis';
/**
* The name of the queue on which to place the broadcasting job.
*
* @var string
*/
public $queue = 'default';
または、イベントにbroadcastQueue
メソッドを定義することでキュー名をカスタマイズできます:
/**
* The name of the queue on which to place the broadcasting job.
*/
public function broadcastQueue(): string
{
return 'default';
}
デフォルトのキュードライバーではなくsync
キューを使用してイベントをブロードキャストしたい場合は、ShouldBroadcastNow
インターフェースを実装することができます。ShouldBroadcast
の代わりに:
<?php
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class OrderShipmentStatusUpdated implements ShouldBroadcastNow
{
// ...
}
Broadcast Conditions
特定の条件が真である場合にのみイベントをブロードキャストしたい場合があります。これらの条件を定義するには、イベントクラスに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;
}
これらの問題を回避する方法については、キューされたジョブとデータベーストランザクションに関するドキュメントを確認してください。
Authorizing Channels
プライベートチャネルでは、現在認証されているユーザーが実際にチャネルでリッスンできることを承認する必要があります。これは、チャネル名を持つHTTPリクエストをLaravelアプリケーションに送信し、ユーザーがそのチャネルでリッスンできるかどうかをアプリケーションに判断させることで実現されます。Laravel Echoを使用する場合、プライベートチャネルへのサブスクリプションを承認するためのHTTPリクエストは自動的に行われます。
ブロードキャスティングが有効になっている場合、Laravelは自動的に/broadcasting/auth
ルートを登録して承認リクエストを処理します。/broadcasting/auth
ルートはweb
ミドルウェアグループ内に自動的に配置されます。
Defining Authorization Callbacks
次に、現在認証されているユーザーが特定のチャネルでリッスンできるかどうかを実際に判断するロジックを定義する必要があります。これは、routes/channels.php
Artisanコマンドによって作成されたファイルで行います。このファイルでは、Broadcast::channel
メソッドを使用してチャネル承認コールバックを登録できます:
use App\Models\User;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
すべての承認コールバックは、現在認証されているユーザーを最初の引数として受け取り、追加のワイルドカードパラメータをその後の引数として受け取ります。この例では、`````{orderId}`````プレースホルダーを使用して、チャネル名の「ID」部分がワイルドカードであることを示しています。
アプリケーションのブロードキャスト承認コールバックのリストは、`````channel:list````` Artisanコマンドを使用して表示できます:
``````shell
php artisan channel:list
`
Authorization Callback Model Binding
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ルートモデルバインディングとは異なり、チャネルモデルバインディングは自動的な暗黙的モデルバインディングスコーピングをサポートしていません。ただし、ほとんどのチャネルは単一のモデルのユニークな主キーに基づいてスコープできるため、これはほとんど問題になりません。
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の他の多くのクラスと同様に、チャネルクラスはサービスコンテナによって自動的に解決されます。したがって、チャネルのコンストラクタで必要な依存関係を型ヒントすることができます。
Broadcasting Events
イベントを定義し、ShouldBroadcast
インターフェースでマークしたら、イベントのdispatchメソッドを使用してイベントを発火するだけです。イベントディスパッチャは、イベントが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つとブロードキャストからの1つです。toOthers
メソッドを使用して、ブロードキャスターに現在のユーザーにイベントをブロードキャストしないよう指示できます。
イベントはIlluminate\Broadcasting\InteractsWithSockets
トレイトを使用する必要があります。toOthers
メソッドを呼び出すために。
Configuration
Laravel Echoインスタンスを初期化すると、接続にソケットIDが割り当てられます。JavaScriptアプリケーションからHTTPリクエストを行うためにグローバルAxiosインスタンスを使用している場合、ソケット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"
}
``````php
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();
``````php
Broadcast::on('orders.'.$order->id)->sendNow();
`
現在認証されているユーザーを除くすべてのチャネルサブスクライバーにイベントをブロードキャストするには、toOthers
メソッドを呼び出すことができます:
Broadcast::on('orders.'.$order->id)
->toOthers()
->send();
Receiving Broadcasts
イベントのリスニング
一度 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
ネームスペースにあると仮定するためです。ただし、Echo をインスタンス化する際に namespace
設定オプションを渡すことで、ルートネームスペースを構成できます:
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
メソッドは 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
メソッドが実行されます。認証エンドポイントが 200 以外の HTTP ステータスコードを返すか、返された JSON の解析に問題がある場合は error
メソッドが実行されます。
プレゼンスチャネルへのブロードキャスト
プレゼンスチャネルは、パブリックまたはプライベートチャネルと同様にイベントを受信できます。チャットルームの例を使用すると、ルームのプレゼンスチャネルに 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 モデルが直接返されました。Eloquent モデルインスタンスがモデルの broadcastOn
メソッドによって返される場合(またはメソッドによって返される配列に含まれる場合)、Laravel はモデルのクラス名と主キー識別子をチャネル名として使用して、モデルのプライベートチャネルインスタンスを自動的にインスタンス化します。
したがって、App\Models\User
モデルの id
が 1
の場合、Illuminate\Broadcasting\PrivateChannel
インスタンスは App.Models.User.1
という名前に変換されます。もちろん、モデルの broadcastOn
メソッドから Eloquent モデルインスタンスを返すだけでなく、モデルのチャネル名を完全に制御するために完全な Channel
インスタンスを返すこともできます:
use Illuminate\Broadcasting\PrivateChannel;
/**
* Get the channels that model events should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(string $event): array
{
return [
new PrivateChannel('user.'.$this->id)
];
}
モデルの broadcastOn
メソッドからチャネルインスタンスを明示的に返す予定がある場合、Eloquent モデルインスタンスをチャネルのコンストラクタに渡すことができます。その際、Laravel は上記で説明したモデルチャネルの慣習を使用して、Eloquent モデルをチャネル名の文字列に変換します:
return [new Channel($this->user)];
モデルのチャネル名を決定する必要がある場合は、任意のモデルインスタンスで broadcastChannel
メソッドを呼び出すことができます。たとえば、このメソッドは 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
メソッドを追加することで、カスタムブロードキャスト名とペイロードを定義できます。これらのメソッドは、発生しているモデルイベント/操作の名前を受け取り、各モデル操作のイベントの名前とペイロードをカスタマイズできます。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],
};
}
モデルブロードキャストのリスニング
モデルに 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);
});
この例では、App\Models\User
インスタンスに broadcast
チャネルを介して送信されたすべての通知がコールバックによって受信されます。App.Models.User.{id}
チャネルのチャネル認可コールバックは、アプリケーションの routes/channels.php
ファイルに含まれています。