Lang x Lang

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 ReverbPusher Channels Ably 、そしてローカル development と debugging 用のlogdriver。さらに、nulldriver が用意されており、これを使うと 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-echopusher-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-echopusher-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 を返すべきです。チャンネルは、ChannelPrivateChannel、またはPresenceChannelのインスタンスであるべきです。Channelのインスタンスは、任意の user が購読できる public チャンネルを表し、一方PrivateChannelsPresenceChannelsは、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 でconnectionqueueプロパティを定義することができます。

/**
 * 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"
}

aswithメソッドを使用して、イベントの名前と 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 を公開するとともに、 herejoining、および 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 は createdupdateddeletedtrashed、または 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 が id1であれば、 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 は、id1App\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 します。

もしご希望であれば、broadcastAsbroadcastWith 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 をリッスンするには、listenForWhispermethod を使うことができます。

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

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use