Reverb を運用しない Laravel Echo
.env の値を変えるだけ。イベント、チャンネル、whisper、toOthers() はそのまま動きます。
Laravel Broadcasting はもともと Pusher プロトコルを話すので、Laravel アプリは組み込みの pusher 接続のまま Hibira にブロードキャストを送れます。イベント、チャンネルルート、Echo のコードは変わりません。なくなるのは、本来自分で動かすはずだった WebSocket サーバーです。常駐する Reverb プロセス、2 台以上に広げるための Redis、スティッキーなロードバランサー、そして夜中にそれを見守る人。
ユーザーにとっての価値
- 注文状況、通知、ダッシュボードがリロードなしで更新されます。
- Echo の
joinとwhisperで、「入力中…」表示とオンライン一覧つきのチャット。 - ページを開いた瞬間から最新の状態。次のイベントまで空のままにはなりません。
使う機能
pusher接続とpusher/pusher-php-serverを使う Laravel Broadcasting。- ブラウザ側は Laravel Echo と
pusher-js。 - 自分の
routes/channels.phpで認可するプライベートチャンネルとプレゼンスチャンネル。 - クライアントイベント(Echo の
whisper)と送信者の除外(toOthers())。 - 最後のイベントを新しい購読者全員に渡すキャッシュチャンネル(
cache-)。
ステップ 1:Broadcasting の向き先を Hibira に
Laravel 11 以降では broadcasting をインストールし、聞かれたら Pusher を選びます。
php artisan install:broadcasting
composer require pusher/pusher-php-server
npm install --save-dev laravel-echo pusher-js続いて .env に接続を設定します。値はアプリのページにあります。
BROADCAST_CONNECTION=pusher
PUSHER_APP_ID=YOUR_APP_ID
PUSHER_APP_KEY=YOUR_APP_KEY
PUSHER_APP_SECRET=YOUR_APP_SECRET
PUSHER_HOST=ws.hibira.io
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=ap
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"Laravel 10 以前では BROADCAST_CONNECTION の代わりに BROADCAST_DRIVER=pusher を使います。標準の config/broadcasting.php はホスト、ポート、スキームを Pusher ライブラリに渡します。手書きの設定ファイルなら、options がそれらを読んでいるか確認してください。そうすれば pusher.com に接続しにいくことはありません。
ステップ 2:Echo を設定する
// resources/js/echo.js
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: 'ap',
wsHost: import.meta.env.VITE_PUSHER_HOST,
wsPort: import.meta.env.VITE_PUSHER_PORT,
wssPort: import.meta.env.VITE_PUSHER_PORT,
forceTLS: import.meta.env.VITE_PUSHER_SCHEME === 'https',
enabledTransports: ['ws', 'wss'],
});ステップ 3:ひとりの顧客にイベントを配信する
class OrderShipped implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(public Order $order) {}
public function broadcastOn(): array
{
return [new PrivateChannel('orders.'.$this->order->id)];
}
}
// routes/channels.php
Broadcast::channel('orders.{id}', fn ($user, $id) => $user->orders()->whereKey($id)->exists());
// Wherever the order ships
OrderShipped::dispatch($order);Echo.private(`orders.${orderId}`)
.listen('OrderShipped', (e) => showStatus(e.order));ShouldBroadcast のイベントはキューを通るので、ワーカー(php artisan queue:work)が動いている必要があります。キューのないプロジェクトでは ShouldBroadcastNow を使えば、リクエスト中に配信されます。
ステップ 4:プレゼンス、whisper、toOthers()
Echo.join(`room.${roomId}`)
.here((users) => online.set(users))
.joining((user) => online.add(user))
.leaving((user) => online.remove(user))
.listen('MessageSent', (e) => messages.append(e.message))
.listenForWhisper('typing', (e) => typing.show(e.name, 3000));broadcast(new MessageSent($message))->toOthers();whisper はクライアントイベントです。アプリ設定で Allow client events をオンにしてください。toOthers() は X-Socket-ID ヘッダーで送信者自身のタブを除外します。Echo は Axios のリクエストにこのヘッダーを自動で付けますが、fetch を使う場合は 'X-Socket-ID': Echo.socketId() を自分で送ってください。ルーム全体の作り方はチャットのユースケースにあります。
ステップ 5:新しいページにも最新の状態を
名前が cache- で始まるチャンネルに配信すると、あとから購読した人にも最後のイベントがすぐ届きます(30 分間保持)。
public function broadcastOn(): array
{
return [new Channel('cache-scoreboard')];
}Echo.channel('cache-scoreboard')
.listen('ScoreUpdated', (e) => board.render(e.scores));Echo.private('cache-orders.1') も同じように動き、private-cache-orders.1 チャンネルになります。
Reverb やほかの Pusher 互換サービスからの移行
変わるのは .env の値だけです。イベント、チャンネルルート、Echo のコードはそのままなので、環境ごとに切り替えられ、戻すのも同じくらい簡単です。確認項目は移行ページに、サインイン後は Laravel ガイドにアプリの値を埋めた同じ設定があります。
ヒント
- 環境(ローカル、ステージング、本番)ごとにアプリを分ければ、テストのイベントが本物のユーザーに届くことはありません。
- プレゼンスチャンネルのメンバーは最大 100 人です。もっと大きなルームは大規模な視聴者を参照してください。
- ブロードキャストは何台のブラウザが受け取っても 1 メッセージとして数えます。配信とプレゼンスの更新は無料です。