Broadcasting
Table of Contents
Introduction
多くの現代の web application では、webSockets がリアルタイムでライブ更新の user インターフェースを実装するために使用されています。何か data が server 上で更新されると、通常 webSocket connection 経由でメッセージが client に送信されて処理されます。webSockets は、UI に反映されるべき data の変更を application の server に絶えずポーリングする代わりに、より効率的な代替手段を提供します。
たとえば、あなたの application が user の data を CSV ファイルにエクスポートしてそれを email で送信できると想像してみてください。しかし、この CSV ファイルの作成には数分かかるため、queue の jobの中で CSV を生成し mail で送ることにします。CSV が作成され、user に mail されたとき、event broadcasting を使用して App\Events\UserDataExported
event を dispatch し、この event は application の JavaScript で受信されます。この event が受信されると、user に対してその CSV が mail で送信されたことを通知するメッセージを表示できます。それにより、user はページを refresh することなくそのことを確認できます。
これらのタイプの features を構築するお手伝いをするために、 Laravel は WebSocket の connection 上でサーバーサイドの Laravel eventsを"broadcast"することを簡単にします。 Broadcasting あなたの Laravel events は、サーバーサイドの Laravel application とクライアントサイドの JavaScript application の間で同じ event 名と data を共有することができます。
broadcasting の背後にある基本的なコンセプトはシンプルです:クライアントはフロントエンドの名前付きチャネルに接続し、 Laravel application はバックエンドでこれらのチャネルに events をブロードキャストします。これらの events は、フロントエンドで利用したい追加の data を含めることができます。
サポートされているドライバー
default として、 Laravel は以下の 3 つのサーバーサイド broadcasting ドライバーを選択できます: Laravel Reverb 、Pusher Channels 、そして Ably 。
NOTE
event broadcasting に深く潜る前に、まず Laravel のドキュメンテーションのevents と listenersを読んでおくことを確認してください。
Server Side Installation
Laravel の event broadcasting を使用し始めるためには、いくつかのパッケージをインストールするだけでなく、 Laravel application 内部でいくつかの設定を行う必要があります。
Event broadcasting は、 Laravel events を Laravel Echo( JavaScript library )がブラウザの client 内で受信できるようにブロードキャストするサーバーサイドの broadcasting driver が実行します。心配しないでください - 私たちは、インストール process の各部分を一歩一歩詳しく説明します。
Configuration
すべてのアプリケーションの event broadcasting 設定は、config/broadcasting.php
設定ファイルに保存されています。このディレクトリがアプリケーションに存在しない場合でも心配は不要です。install:broadcasting
Artisan command を実行すると生成されます。
Laravel は、以下のようないくつかの broadcastingdriver ーをすぐに使用できます。 Laravel Reverb、 Pusher Channels 、 Ably 、そしてローカル development と debugging 用のlog
driver。さらに、null
driver が用意されており、これを使うと testing 中に broadcast を無効にすることができます。これらの各 driver ーについての設定例は、config/broadcasting.php
設定ファイルに記載されています。
Installation
default では、新しい Laravel application では 放送 が有効になっていません。install:broadcasting
Artisan command を使用して 放送 を有効にすることができます。
php artisan install:broadcasting
install:broadcasting
の command はconfig/broadcasting.php
設定ファイルを作成します。さらに、command はあなたの application の broadcastauthenticationroutes とコールバックを登録できるroutes/channels.php
ファイルを作成します。
Queue 設定
何か events を broadcasting する前に、まずqueue workerを設定して実行する必要があります。すべての event broadcasting は、application の response 時間が events の broadcast によって深刻に影響を受けないように、キューされた jobsvia で行われます。
Reverb
install:broadcasting
の command を実行すると、Laravel Reverbのインストールを求められます。もちろん、 Composer パッケージマネージャーを使用して手動で Reverb をインストールすることも可能です。Reverb は現在ベータ版のため、明示的にベータの release をインストールする必要があります。
composer require laravel/reverb:@beta
パッケージがインストールされると、設定を publish したり、Reverb の required environment 変数を追加したり、 application での event broadcasting を有効にしたりするために、Reverb のインストールの command を実行できます:
php artisan reverb:install
詳細な Reverb のインストールと使用方法については、Reverb documentationで確認できます。
Pusher Channels
Pusher Channels を使ってあなたの events を broadcast する予定がある場合、 Composer パッケージマネージャを使って Pusher Channels PHP SDK をインストールする必要があります:
composer require pusher/pusher-php-server
次に、config/broadcasting.php
の設定ファイルで Pusher Channels の認証情報を設定する必要があります。このファイルにはすでに Pusher Channels の設定例が含まれており、キー、 secret 、そして application 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
設定では、Channels がサポートする追加の options
、例えばクラスタといったものを指定することも可能です。
次に、アプリケーションの .env
ファイルで BROADCAST_CONNECTION
environment 変数を pusher
に設定します:
BROADCAST_CONNECTION=pusher
ついに、クライアント側で broadcast events を受信するLaravel Echoをインストールして設定する準備が整いました。
Ably
NOTE
以下のドキュメンテーションでは、Ably を"Pusher compatibility"モードで使用する方法について説明します。ただし、Ably チームは、Ably が提供する unique な機能を活用できる broadcaster と Echo の client を推奨し、メンテナンスしています。Ably がメンテナンスしているドライバーの使用方法についての詳細は、Ably の Laravel broadcaster のドキュメント を参照してください。
Ably を使用してあなたの events を broadcast する予定がある場合は、 Composer パッケージマネージャーを使用して Ably PHP SDK をインストールする必要があります:
composer require ably/ably-php
次に、config/broadcasting.php
設定ファイルで Ably の資格情報を設定する必要があります。このファイルにはすでに Ably の設定の例が含まれており、すぐにキーを指定することができます。通常、この value はABLY_KEY
environment 変数を介して設定する必要があります。
ABLY_KEY=your-ably-key
次に、アプリケーションの.env
ファイルで、BROADCAST_CONNECTION
environment 変数を ably
に設定します:
BROADCAST_CONNECTION=ably
ついに、クライアント側で broadcast events を受信するLaravel Echoをインストールし、設定する準備が整いました。
Client Side Installation
Reverb
Laravel Echo は、servers サイドの broadcasting driver から events を broadcast したり、channels に登録しやすくする JavaScript library です。NPM パッケージマネージャーを通じて Echo をインストールできます。この例では、Reverb が WebSocket の subscriptions、channels、メッセージに Pusher プロトコルを利用しているため、pusher-js
パッケージもインストールします。
npm install --save-dev laravel-echo pusher-js
Echo がインストールされたら、application の JavaScript で新しい Echo インスタンスを作成する準備が整います。これを行うのに最適な場所は、Laravel フレームワークに含まれるresources/js/bootstrap.js
ファイルの末尾です。default では、このファイルにはすでに Echo の設定例が含まれています - あなたはそれをアン comment するだけで、broadcaster
設定 option を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
WARNING
Laravel Echo の
reverb
ブロードキャスターは、Laravel-echo v1.16.0 以降が必要です。
Pusher Channels
Laravel Echo は、servers サイドの放送 driver によって broadcast される events をリッスンし、channels への購読を容易にする JavaScript library です。Echo はまた、pusher-js
NPM パッケージを利用して、WebSocket の購読、channels、メッセージのための Pusher プロトコルを実装します。
install:broadcasting
の Artisan command は自動的にlaravel-echo
とpusher-js
のパッケージをインストールしますが、NPM を使って手動でこれらのパッケージをインストールすることも可能です。
npm install --save-dev laravel-echo pusher-js
Echo がインストールされると、アプリケーションの JavaScript に新しい Echo インスタンスを作成する準備が整います。 install:broadcasting
command は、 resources/js/echo.js
に Echo の設定ファイルを作成しますが、このファイルの default 設定は 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 の environment 変数に対して適切な values を定義する必要があります。これらの変数が既に .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
NOTE
ご自身のアプリケーションの JavaScript アセットのコンパイルについて詳しく学ぶには、Viteに関するドキュメンテーションをご参照ください。
既存の Client インスタンスを使用する
すでに設定済みの Pusher Channels client インスタンスがあり、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
NOTE
以下のドキュメンテーションでは、Ably を"Pusher 互換性"モードで使う方法について説明します。しかし、Ably チームは、Ably が提供する unique な機能を活用できる broadcaster と Echo の client を推奨し、維持しています。Ably が維持しているドライバーの使用に関する詳細情報は、Ably の Laravel broadcaster ドキュメンテーション をご覧ください。
Laravel Echo は、チャンネルへの subscribe を容易にし、サーバーサイドの broadcasting driver によって events broadcast を待ち受ける JavaScript library です。Echo はまた、WebSocket の subscriptions、チャネル、メッセージのための Pusher プロトコルを実装するために pusher-js
NPM パッケージを活用します。
install:broadcasting
の Artisan command は、自動的にlaravel-echo
とpusher-js
のパッケージをインストールします。しかし、これらのパッケージは NPM を通じて手動でインストールすることも可能です:
npm install --save-dev laravel-echo pusher-js
続ける前に、Ably の application 設定で Pusher プロトコルのサポートを有効にする必要があります。この feature は、Ably アプリケーションの設定ダッシュボード内の"Protocol Adapter Settings"部分で有効にすることができます。
Echo がインストールされたら、アプリケーションの JavaScript で新しい Echo インスタンスを作成する準備が整います。install:broadcasting
command は、resources/js/echo.js
に Echo の設定ファイルを作成しますが、このファイルの default の設定は 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
environment 変数を参照していることに気づいたかもしれません。この変数の value は、あなたの Ably public key であるべきです。あなたの public key は、Ably key の中で:
文字の前に出現する部分です。
あなたのニーズに合わせて Echo の設定を調整したら、アプリケーションのアセットをコンパイルすることができます:
npm run dev
NOTE
ご自身のアプリケーションの JavaScript アセットをコンパイルする方法について詳しく知るには、Viteのドキュメンテーションをご参照ください。
Concept Overview
Laravel の event broadcasting は、driver 主導のアプローチを用いて、servers サイドの Laravel events を client サイドの JavaScript application に broadcast することを可能にします。現在、Laravel は Pusher Channels と Ably の driver を搭載しています。client サイドでの events の使用は、Laravel Echo JavaScript パッケージを用いて容易に行うことができます。
Events"は"channels"を介して"broadcast"され、"public"または"private"と指定することができます。"application"を訪れるどんな訪問者も、"authentication"や承認なしに"public channel"に"subscribe"することができます。しかし、"private channel"に"subscribe"するためには、"user"がその"channel"を聴取するために authentication および承認を受ける必要があります。
例を使った Application の使用方法
event broadcasting の各 component に深く詳しく入る前に、電子商取引ストアを例に取り、高レベルでの概観を見てみましょう。
私たちの application では、 users が注文の配送 status を view するページがあると仮定しましょう。また、配送 status update が application で処理されるときに、OrderShipmentStatusUpdated
event が発火すると仮定しましょう。
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
ShouldBroadcast
インターフェース
user が自分の注文の一つを閲覧しているとき、 view status の更新を見るためにページを refresh する必要がないようにしたいと考えています。代わりに、更新情報を作成するたびに application に broadcast したいと思います。だから、 OrderShipmentStatusUpdated
event にShouldBroadcast
インターフェースをマークする必要があります。これにより、 Laravel が event が開始されたときにそれを broadcast するよう指示します:
<?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
インターフェースは、我々の event がbroadcastOn
method を定義することを要求します。この method は、 event がどのチャンネルで broadcast すべきかを返す責任があります。この method の空のスタブはすでに生成された event クラスに定義されているので、詳細を埋め込むだけで済みます。私たちは、注文の作成者だけが view status の更新を表示できるようにしたいので、 event を注文に紐づいた private channel で broadcast します。
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
を代わりに返すことで、 event を複数のチャンネルで broadcast することを希望する場合があります:
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),
// ...
];
}
チャンネルの認証
覚えておいてください、 users は、 private チャンネルでのリスニングを許可されていなければなりません。 我々は、アプリケーションの routes/channels.php
ファイルで、我々の channel authorization ルールを定義することができます。 この例では、 user が private orders.1
channel をリスニングしようとしているかどうかを確認する必要があります。そしてそれが実際にはその注文の作成者であるかどうかを確認します。
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
の method は、2 つの引数を受け取ります: channel の名前と、true
またはfalse
を返すコールバック、これは user が channel でのリッスンが許可されているかどうかを示します。
すべての authorization コールバックは、現在認証されている user を最初の引数として受け取り、その後の引数として追加のワイルドカードパラメータを受け取ります。この例では、{orderId}
プレースホルダーを使用して、 channel 名の"ID"部分がワイルドカードであることを示しています。
Event ブロードキャストのリスニング
次に、残すは JavaScript application で event をリッスンするだけです。これは、Laravel Echoを使用して行うことができます。まず、private
method を使用して private channel に subscribe します。その後、listen
method を使って、OrderShipmentStatusUpdated
event をリッスンすることができます。 default では、イベントのすべての public プロパティが broadcast event に含まれるでしょう。
Echo.private(`orders.${orderId}`).listen("OrderShipmentStatusUpdated", (e) => {
console.log(e.order);
});
Defining Broadcast Events
特定の event が broadcast されるべきだと Laravel に通知するためには、 event class にIlluminate\Contracts\Broadcasting\ShouldBroadcast
インターフェースを実装する必要があります。このインターフェースは、フレームワークによって生成されたすべての event クラスにすでにインポートされているため、自分の events に簡単に追加することができます。
ShouldBroadcast
インターフェースでは、broadcastOn
という単一のメソッドを実装する必要があります。broadcastOn
method は、event が放送すべき channel または channel の array を返すべきです。チャンネルは、Channel
、PrivateChannel
、またはPresenceChannel
のインスタンスであるべきです。Channel
のインスタンスは、任意の user が購読できる public チャンネルを表し、一方PrivateChannels
とPresenceChannels
は、channelauthenticationが必要なプライベートチャンネルを表します:
<?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
インターフェースを実装した後、通常どおりに event を発火するだけです。一度 event が発火されると、指定した broadcast driver を使用して event を自動的に broadcast するキュー化された jobが自動的に開始されます。
Broadcast 名
default では、 Laravel はイベントの class 名を使用して event を broadcast します。しかし、 event の上でbroadcastAs
method を定義することで、 broadcast の名前をカスタマイズすることができます。
/**
* The event's broadcast name.
*/
public function broadcastAs(): string
{
return 'server.created';
}
broadcastAs
method を使用して broadcast 名をカスタマイズする場合、listener を先頭の .
文字で register することを確認してください。これにより、Echo は application の名前空間を event の前に追加しないよう指示します。
.listen('.server.created', function (e) {
....
});
Broadcast Data
event が broadcast されると、そのすべてのpublic
プロパティが自動的にシリアライズされ、イベントのペイロードとして broadcast されます。これにより、 JavaScript application からその任意の public data にアクセスすることが可能になります。つまり、例えば、あなたの event が single public の$user
プロパティを含む Eloquent model である場合、そのイベントの broadcast ペイロードは次のようになります:
{
"user": {
"id": 1,
"name": "Patrick Stewart"
...
}
}
ただし、 broadcast ペイロードに対してより詳細なコントロールを望む場合は、broadcastWith
method をあなたの event に追加することができます。この method は、あなたが broadcast したい data の array を event ペイロードとして返すべきです:
/**
* Get the data to broadcast.
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
return ['id' => $this->user->id];
}
Broadcast Queue
default として、各 broadcast event は、あなたのqueue.php
設定ファイルで指定されている default queue 接続の default queue に配置されます。ブロードキャスターで使用される queue 接続と名前をカスタマイズするために、あなたの event class で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
method をあなたの event 上で定義することにより、 queue 名をカスタマイスすることもできます。
/**
* The name of the queue on which to place the broadcasting job.
*/
public function broadcastQueue(): string
{
return 'default';
}
sync
の queue を使用して、default のキュー driver の代わりに event を放送したい場合は、ShouldBroadcast
の代わりにShouldBroadcastNow
インターフェースを実装できます。
<?php
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class OrderShipmentStatusUpdated implements ShouldBroadcastNow
{
// ...
}
Broadcast の条件
時折、与えられた条件が true である場合にのみ、あなたの event を broadcast したいと思うことがあるでしょう。これらの条件は、あなたの event class にbroadcastWhen
method を追加することで定義することができます:
/**
* Determine if this event should broadcast.
*/
public function broadcastWhen(): bool
{
return $this->order->value > 100;
}
Broadcasting と Database Transactions
broadcast events が database transactions 内でディスパッチされると、 database transaction がコミットされる前に queue によって処理される場合があります。これが起こると、 database transaction の最中に models や database のレコードに対して行った更新が、 database にまだ反映されていない場合があります。さらに、 transaction 内で作成された models や database のレコードが database に存在しない場合もあります。 event がこれらの models に依存している場合、 event をブロードキャストする job が処理される際に予期しない errors が発生することがあります。
あなたの queue 接続のafter_commit
の設定オプションがfalse
に設定されている場合でも、特定の broadcast event がすべての開いている database transactions がコミットされた後にディスパッチされるべきことを示すことができます。これは、 event class で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;
}
NOTE
これらの問題を回避する方法について詳しく知るために、queue 内の jobs と database transactionsに関するドキュメンテーションをご覧ください。
Authorizing Channels
Private チャンネルでは、現在認証されている user が実際にその channel でリスンできることを authorize する必要があります。これは、 channel の名前を用いてあなたの Laravel application への HTTP request を作成し、 application がその user がその channel でリスンできるかどうかを判断することで達成されます。Laravel Echoを使用している場合、 private チャンネルへの authorize subscriptions への HTTP request は自動的に行われます。
broadcasting が有効化されると、 Laravel は自動的に/broadcasting/auth
route を登録し、 handle authorization リクエストを処理します。/broadcasting/auth
route は自動的にweb
middleware グループ内に配置されます。
Authorization コールバックの定義
次に、現在認証済みの user が特定の channel を聴けるかどうかを実際に判定するロジックを定義する必要があります。これは、install:broadcasting
Artisan command によって作成されたroutes/channels.php
ファイルで行います。このファイルでは、Broadcast::channel
method を使用して register channel authorization コールバックを登録することができます:
use App\Models\User;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
channel
method は、2 つの引数を受け取ります: channel の名前と、 user が channel での待ち受けを許可するかどうかを示す true
または false
を返すコールバック。
すべての authorization コールバックは、現在認証済みの user を最初の引数として受け取り、その他のワイルドカードパラメータをその後の引数として受け取ります。この例では、 {orderId}
プレースホルダを使用して、 channel 名の "ID" 部分がワイルドカードであることを示しています。
あなたは channel:list
の Artisan command を使用して、アプリケーションの broadcast authorization コールバックのリストを view することができます:
php artisan channel:list
Authorization コールバック Model バインディング
HTTP ルートと同様に、channel ルートも暗黙的および明示的なルート model バインディングを利用できます。例えば、string や数 values のオーダー ID を受け取る代わりに、実際のOrder
model インスタンスを request することができます:
use App\Models\Order;
use App\Models\User;
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
return $user->id === $order->user_id;
});
WARNING
HTTProutemodel バインディングとは異なり、channelsmodel バインディングは自動的な暗黙の model バインディング scopeをサポートしていません。しかし、ほとんどの channels はシングル model の unique で primary な key に基づいて scope 化することができるため、これはほとんど問題になりません。
Authorization コールバック Authentication
Private と broadcast チャンネルはアプリケーションの default authentication ガードを通じて現在の user を認証します。 user が認証されていない場合、 channel authorization は自動的に拒否され、 authorization コールバックは実行されません。しかし、必要に応じて request を認証するべき複数の custom ガードを割り当てることが可能です。
Broadcast::channel('channel', function () {
// ...
}, ['guards' => ['web', 'admin']]);
Channel クラスの定義
もし、あなたの application が多くの異なるチャネルを消費している場合、あなたの routes/channels.php
ファイルはかさばるかもしれません。そのため、チャネルを authorize するためにクロージャを使用する代わりに、 channel クラスを使用することができます。 channel class を生成するには、 make:channel
Artisan command を使用します。 この command は新たな channel class を App/Broadcasting
ディレクトリに作成します。
php artisan make:channel OrderChannel
次に、routes/channels.php
ファイルで channel に register してください:
use App\Broadcasting\OrderChannel;
Broadcast::channel('orders.{order}', OrderChannel::class);
最後に、あなたの channel のための authorization ロジックを、 channel クラスのjoin
method に配置することができます。このjoin
method には、通常あなたが channel authorization クロージャに置いていた同じロジックが格納されます。また、 channel model バインディングを活用することもできます:
<?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;
}
}
NOTE
Laravel の他の多くのクラスと同様に、 channel クラスは自動的にservice containerによって解決されます。したがって、コンストラクタで channel が required する任意の依存関係をタイプヒントとして指定することができます。
Broadcasting Events
ShouldBroadcast
インターフェースを使用して event を定義し、マークしたら、その event を dispatch method を使用して発火するだけで良いです。 event ディスパッチャーは、 event が ShouldBroadcast
インターフェースでマークされていることに気付き、その event を broadcasting のために queue に入れます。
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
他人にだけ
event broadcasting を利用する application を構築する際に、特定の channel のすべてのサブスクライバーに対して現在の user を除いて event を broadcast する必要がある場合があります。これは、broadcast
ヘルパーとtoOthers
method を使用して実現できます:
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->toOthers();
toOthers
method をいつ使用したいかをより理解するために、タスク名を入力して新たなタスクを作成する可能性があるタスクリストの application を想像してみましょう。タスクを作成するために、あなたの application は/task
URL への request を作るかもしれません、これはタスクの作成を broadcasts し、新たなタスクの JSON 表現を返します。あなたの JavaScript application がエンドポイントからの response を受け取ったとき、新たなタスクをそのタスクリストに直接挿入するかもしれません、次のように:
axios.post("/task", task).then((response) => {
this.tasks.push(response.data);
});
ただし、タスクの作成を broadcast も行うことを覚えておいてください。もし JavaScript application がこの event をリッスンしてタスクリストにタスクを追加するなら、リスト内に重複したタスクが表示されるでしょう:1つはエンドポイントから、もう1つは broadcast からです。これを解決するには、 toOthers
“method を使用して、現在の “user に対して broadcast を行わないようにブロードキャスターに指示します。
WARNING
あなたの event は、
toOthers
method を呼び出すためには、Illuminate\Broadcasting\InteractsWithSockets
trait を使用する必要があります。
Configuration
Laravel Echo インスタンスを初期化すると、ソケット ID が connection に割り当てられます。もし、グローバルな Axios のインスタンスを使って、ご自身の JavaScript application から HTTP requests を行っている場合、ソケット ID は自動的にすべての発信 request に X-Socket-ID
ヘッダ として添付されます。その後、toOthers
method を呼び出すと、 Laravel は ヘッダ からソケット ID を抽出し、そのソケット ID のある全ての接続先に対して broadcast しないようにブロードキャスターに指示します。
グローバルな Axios インスタンスを使用していない場合、すべての送信リクエストにX-Socket-ID
header を送信するように JavaScript application を手動で設定する必要があります。Echo.socketId
method を使用してソケット ID を取得できます:
var socketId = Echo.socketId();
Connection のカスタマイズ
あなたの application が複数の broadcast 接続と対話し、 default 以外のブロードキャスターを使用して event を broadcast したい場合、via
method を使用してどの connection に event をプッシュするかを指定することができます:
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->via('pusher');
あるいは、event のコンストラクタ内でbroadcastVia
method を呼び出すことにより、event の broadcast 接続を指定することもできます。ただし、その前に、eventclass が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');
}
}
匿名 Events
時々、専用の event class を作成せずに単純な event を application のフロントエンドに broadcast したい場合があります。これに対応するため、Broadcast
facade を使って"anonymous events"を broadcast できます。
Broadcast::on('orders.'.$order->id)->send();
上記の例では、次の event を broadcast します:
{
"event": "AnonymousEvent",
"data": "[]",
"channel": "orders.1"
}
as
とwith
メソッドを使用して、イベントの名前と data をカスタマイズできます。
Broadcast::on('orders.'.$order->id)
->as('OrderPlaced')
->with($order)
->send();
上記の例は、以下のような event を broadcast します。
{
"event": "OrderPlaced",
"data": "{ id: 1, total: 100 }",
"channel": "orders.1"
}
匿名の event を private または presencechannel で broadcast したい場合は、private
およびpresence
メソッドを利用できます:
Broadcast::private('orders.'.$order->id)->send();
Broadcast::presence('channels.'.$channel->id)->send();
send
method を使って匿名の event を 放送 すると、その event が application のqueueに 処理 のために送信されます。しかし、もし event をすぐに 放送 したい場合は、sendNow
method を使用することができます:
Broadcast::on('orders.'.$order->id)->sendNow();
toOthers
method を使用して、現在 authentication されている user を除くすべての channel の購読者に event を broadcast できます。
Broadcast::on('orders.'.$order->id)
->toOthers()
->send();
Receiving Broadcasts
Events のリスニング
Laravel Echoをインストールして実体化が完了したら、Laravel アプリケーションから broadcast される events を監視する準備が整います。まず、channel
method を使用して channel のインスタンスを取得し、その後でlisten
method を呼び出して指定された events を監視します。
Echo.channel(`orders.${this.order.id}`).listen(
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order.name);
}
);
もし private channel 上の events を聞きたい場合は、代わりにprivate
method を使用してください。listen
method に対する呼び出しを続けて、 single channel 上で複数の events を聞くことも可能です。
Echo.private(`orders.${this.order.id}`)
.listen(/* ... */)
.listen(/* ... */)
.listen(/* ... */);
Events のリスニングを停止する
特定の event を聞くのを止めたい場合に、channel を退出せずに、stopListening
method を使用することができます。
Echo.private(`orders.${this.order.id}`).stopListening(
"OrderShipmentStatusUpdated"
);
Channel を離れる
Echo インスタンスでleaveChannel
method を呼び出すことで、 channel から退出することができます。
Echo.leaveChannel(`orders.${this.order.id}`);
channel を離れて、関連する private とプレゼンスチャンネルも離れたい場合は、leave
method を呼び出すことができます:
Echo.leave(`orders.${this.order.id}`);
Namespaces
上記の例でお気づきかもしれませんが、 App\Events
ネームスペースの完全な指定を event クラスには行っていません。これは、Echo が App\Events
ネームスペースに events が存在することを自動的に想定しているからです。ただし、namespace
設定オプションを指定して Echo をインスタンス化するときに、 root ネームスペースを設定することもできます:
window.Echo = new Echo({
broadcaster: "pusher",
// ...
namespace: "App.Other.Namespace",
});
あるいは、Echo を使用してこれらにサブスクライブするときに、.
を付けて event クラスをプレフィックスとして使用することもできます。これにより、常に完全修飾の class 名を指定することができます。
Echo.channel("orders").listen(".Namespace\\Event\\Class", (e) => {
// ...
});
Presence Channels
Presence channels は、privatechannel のセキュリティを基盤にしながら、誰が channel に subscribed しているかの認識を可能にする追加 feature を提供します。これにより、同じページを見ている別の user に user が通知したり、チャットルームの住人をリストにしたりするなど、強力で協力的な application features を build することが簡単になります。
Presence チャンネルの認証
すべてのプレゼンスチャネルもまた、 private チャネルであり、そのため、 users はそれらにアクセスするために認可される必要があります。しかし、プレゼンスチャネルの authorization コールバックを定義する際、 user が channel に join するために認可されている場合、true
を返すのではありません。代わりに、 user に関する data の array を返すべきです。
authorization コールバックによって返される data は、あなたの JavaScript application での presence channel event listeners に利用可能になります。もし user が presence channel に join することを許可されていない場合、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];
}
});
Presence チャンネルへの参加
プレゼンス channel に join するには、Echo の join
method を使用することができます。 join
method は PresenceChannel
実装を返し、これにより listen
method を公開するとともに、 here
、joining
、および leaving
events に subscribe することが可能になります。
Echo.join(`chat.${roomId}`)
.here((users) => {
// ...
})
.joining((user) => {
console.log(user.name);
})
.leaving((user) => {
console.log(user.name);
})
.error((error) => {
console.error(error);
});
here
コールバックは、channel が正常に参加した直後にすぐに実行され、他の user 全員の user 情報を含む array を channel に登録している。joining
method は新しい user が channel に参加するときに実行され、一方、leaving
method は user が channel を離れるときに実行されます。error
method は、authentication エンドポイントが 200 以外の HTTP status コードを返すか、返された JSON の解析に問題がある場合に実行されます。
Broadcasting にプレゼンスチャネルへの送信
Presence チャネルは、 public チャネルや private チャネルと同じように events を受け取ることができます。例えばチャットルームの例を使うと、私たちは NewMessage
events をチャットルームの presence channel に broadcast したいかもしれません。そのためには、イベントの broadcastOn
method から 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),
];
}
他の events と同様に、broadcast
ヘルパーとtoOthers
method を使用して、現在の user が broadcast を受信しないようにすることができます:
broadcast(new NewMessage($message));
broadcast(new NewMessage($message))->toOthers();
他のタイプの events と同様に、Echo のlisten
method を使用して、presence チャネルに送信された events をリスンすることができます:
Echo.join(`chat.${roomId}`)
.here(/* ... */)
.joining(/* ... */)
.leaving(/* ... */)
.listen("NewMessage", (e) => {
// ...
});
Model Broadcasting
WARNING
次の model broadcasting に関する文書を読む前に、Laravel の model broadcasting services の一般的な概念、および broadcast events の手動作成とリスニング方法について理解することをお勧めします。
あなたのアプリケーションのEloquent modelsが作成、更新、または削除されたときに、 broadcast events を行うことが一般的です。もちろん、これは手動でEloquent model state の変更に対して custom events を定義し、それらの events を ShouldBroadcast
インターフェースでマークすることで簡単に実現できます。
しかし、これらの events を application 内で他の目的に使用していない場合、それらを broadcasting するためだけに event クラスを作成することは面倒です。これを解決するために、 Laravel では Eloquent model が自動的にその state の変化を broadcast することを指定できます。
始めるには、あなたの Eloquent model はIlluminate\Database\Eloquent\BroadcastsEvents
トレイトを使うべきです。加えて、 model はbroadcastOn
method を定義するべきです。これはモデルの events が broadcast すべきチャンネルの array を返します:
<?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];
}
}
あなたの model がこのトレイトを含み、その broadcast チャネルを定義すると、 model インスタンスが作成、更新、削除、ゴミ箱に入れられ、または復元されたときに、自動的に broadcasting events を開始します。
また、broadcastOn
method が string の $event
引数を受け取ることに気づいたかもしれません。この引数には、 model で発生した event の type が含まれ、その value は created
、updated
、deleted
、trashed
、または restored
になります。この variables の value を調べることで、 model が特定の event に対して broadcast すべき channels(存在する場合)を決定することができます:
/**
* 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],
};
}
Model Broadcasting Event 作成のカスタマイズ
たまに、 Laravel が基本的な model broadcasting event を作成する方法をカスタマイズしたいと思うかもしれません。これは、あなたの Eloquent model でnewBroadcastableEvent
method を定義することで達成できます。この method はIlluminate\Database\Eloquent\BroadcastableModelEventOccurred
インスタンスを返すべきです。
use Illuminate\Database\Eloquent\BroadcastableModelEventOccurred;
/**
* Create a new broadcastable model event for the model.
*/
protected function newBroadcastableEvent(string $event): BroadcastableModelEventOccurred
{
return (new BroadcastableModelEventOccurred(
$this, $event
))->dontBroadcastToCurrentUser();
}
Model Broadcasting 規約
Channel の規約
お気づきかもしれませんが、上記の model の例でのbroadcastOn
method は、Channel
のインスタンスを返しませんでした。代わりに、 Eloquent models が直接返されました。もしbroadcastOn
method が(または array が method によって返される)あなたのモデルの Eloquent model のインスタンスを返す場合、 Laravel は自動的にモデルの class 名と primary key 識別子を使用して model のための private channel インスタンスを生成します。 channel の名前としてです。
それで、App\Models\User
の model が id
が1
であれば、 Illuminate\Broadcasting\PrivateChannel
インスタンスに変換され、その名前は App.Models.User.1
になります。もちろん、モデルのbroadcastOn
method から Eloquent model のインスタンスを返すだけでなく、モデルの channel 名の完全な制御を持つために、完全な 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)
];
}
model の broadcastOn
method から明示的に channel インスタンスをリターンする予定の場合、 Eloquent model のインスタンスをチャンネルのコンストラクタに渡すことができます。そうすると、 Laravel は上記で議論した model channel の規約を使用して、 Eloquent model を channel 名の string に変換します:
return [new Channel($this->user)];
model の channel 名を決定する必要がある場合、任意の model インスタンスでbroadcastChannel
method を呼び出すことができます。例えば、この method は、id
が1
のApp\Models\User
model に対して string App.Models.User.1
を返します。
$user->broadcastChannel()
Event コンベンション
App\Events
ディレクトリ内の "実際の" event と関連付けられていないため、 model broadcast events には、規約に基づいて名前とペイロードが割り当てられます。Laravel の規約では、 broadcast を event として、 model の class 名(名前空間は含まれません)とトリガーした model event の名前を使用して broadcast します。
つまり、例えば、App\Models\Post
の model にアップデートがあると、あなたの client サイドの application に event を broadcast し、以下のペイロードでPostUpdated
として送信します:
{
"model": {
"id": 1,
"title": "My first post"
...
},
...
"socket": "someSocketId",
}
App\Models\User
model の削除は、UserDeleted
という名前の event を broadcast します。
もしご希望であれば、broadcastAs
とbroadcastWith
method をあなたの model に追加することで、 custom broadcast の名前とペイロードを定義することができます。これらのメソッドは、発生している model event / 操作の名前を受け取り、各 model 操作のイベント名とペイロードをカスタマイズすることが可能です。 broadcastAs
method からnull
が返された場合、 Laravel は上記で説明した model broadcasting event 名の規則を使用して event を broadcasting します:
/**
* 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],
};
}
Model ブロードキャストのリスニング
BroadcastsEvents
トレイトをあなたの model に追加し、モデルの broadcastOn
method を定義したら、クライアントサイドの application でブロードキャストされた model events を待ち受ける準備が整います。始める前に、events の待ち受けに関する完全なドキュメントを参照することをお勧めします。
まず、private
method を使用して channel のインスタンスを取得し、次に listen
method を呼び出して指定の event を待ち受けます。通常、private
method に与えられる channel の名前は、Laravel のmodel broadcasting の規約に対応するべきです。
channel インスタンスを取得したら、特定の event を待ち受けるために listen
method を使用できます。 modelbroadcastevent は application のApp\Events
ディレクトリ内の実際の event と関連付けられていないため、event 名では特定のネームスペースに属していないことを示すために.
が接頭辞として付けられる必要があります。modelbroadcastevent はそれぞれがmodel
プロパティを持っており、それには model の broadcast 可能なすべてのプロパティが含まれています:
Echo.private(`App.Models.User.${this.user.id}`).listen(".PostUpdated", (e) => {
console.log(e.model);
});
Client Events
NOTE
Pusher Channels を使用する際には、あなたのapplication ダッシュボード の "App Settings" セクションで "client events" option を有効にする必要があります。これにより、clientevent を送信することができます。
時々、あなたは Laravel application に全く接触せずに、他の接続されたクライアントに event を broadcast したいと思うことがあるかもしれません。これは、typing のような notifications で特に便利で、あなたの application の他の user が特定の画面でメッセージを入力していることを alert users に知らせたいときに便利です。
clientevent を broadcast するためには、Echo の whisper
method を使用することができます:
Echo.private(`chat.${roomId}`).whisper("typing", {
name: this.user.name,
});
clientevent をリッスンするには、listenForWhisper
method を使うことができます。
Echo.private(`chat.${roomId}`).listenForWhisper("typing", (e) => {
console.log(e.name);
});
Notifications
event broadcasting とnotificationsを組み合わせることで、あなたの JavaScript application はページを refresh することなく新しい notifications を受け取ることができます。開始する前に、broadcast notification channelの使用に関するドキュメンテーションを読むことを忘れないでください。
notification を broadcast channel で使用するように設定したら、Echo のnotification
method を使用して broadcast events を聞くことができます。channel の名前は、notifications を受け取るエンティティの class 名と match する必要があります:
Echo.private(`App.Models.User.${userId}`).notification((notification) => {
console.log(notification.type);
});
この例では、すべての notifications が App\Models\User
インスタンスに broadcast
channel 経由で送信され、コールバックによって受け取られます。 App.Models.User.{id}
channel の channel authorization コールバックは、アプリケーションの routes/channels.php
ファイルに含まれています。