株式会社WR

株式会社WR

WEB TOTAL CONSULTING

Laravel Reverbでリアルタイム機能を実装——予約状況のライブ更新
ブログ一覧へ
技術ブログ

Laravel Reverbでリアルタイム機能を実装——予約状況のライブ更新

Laravel Reverb(公式WebSocketサーバー)を使うと、予約・在庫のリアルタイム更新が外部サービスなしに実装できます。

Laravel Reverbとは——PHPネイティブなWebSocketサーバー

Laravel Reverbは2024年3月のLaravel 11と同時にリリースされた、Laravelアプリにネイティブ統合できるWebSocketサーバーです。従来はPusher・Soketi・SocketIOなどの外部サービス・ツールが必要でしたが、Reverbを使えば追加コストなしで自前のWebSocketサーバーを運用できます。


インストール

composer require laravel/reverb

php artisan reverb:install
# → config/reverb.php が生成される
# → .env に REVERB_* 変数が追加される

# フロントエンドライブラリのインストール
npm install --save-dev laravel-echo pusher-js

環境設定

# .env
BROADCAST_CONNECTION=reverb

REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-secret
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=http

ブロードキャストイベントの定義

// app/Events/ReservationStatusUpdated.php
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class ReservationStatusUpdated implements ShouldBroadcast
{
    use Dispatchable, SerializesModels;

    public function __construct(
        public readonly Reservation $reservation,
    ) {}

    // イベントのブロードキャスト先チャンネル
    public function broadcastOn(): array
    {
        return [
            // プライベートチャンネル(認証が必要)
            new PrivateChannel("reservations.{$this->reservation->id}"),
            // 管理者向けチャンネル
            new PrivateChannel('admin.reservations'),
        ];
    }

    // ブロードキャストするデータ
    public function broadcastWith(): array
    {
        return [
            'reservation_id' => $this->reservation->id,
            'status'         => $this->reservation->status,
            'updated_at'     => $this->reservation->updated_at->toIso8601String(),
            'customer_name'  => $this->reservation->customer_name,
        ];
    }

    // イベント名のカスタマイズ
    public function broadcastAs(): string
    {
        return 'reservation.status.updated';
    }
}

チャンネル認証

// routes/channels.php
use App\Models\Reservation;

// ユーザーが自分の予約チャンネルにアクセスできるか認証
Broadcast::channel('reservations.{reservationId}', function ($user, int $reservationId) {
    $reservation = Reservation::find($reservationId);
    return $reservation && $reservation->user_id === $user->id;
});

// 管理者のみアクセス可能
Broadcast::channel('admin.reservations', function ($user) {
    return $user->isAdmin();
});

イベントのdispatch

// コントローラー
class ReservationController extends Controller
{
    public function confirm(Reservation $reservation): JsonResponse
    {
        $reservation->update(['status' => 'confirmed']);

        // イベントをブロードキャスト
        ReservationStatusUpdated::dispatch($reservation);

        return response()->json(['message' => '予約を確定しました']);
    }
}

フロントエンドの実装

// resources/js/bootstrap.js
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 ?? 80,
    wssPort:     import.meta.env.VITE_REVERB_PORT ?? 443,
    forceTLS:    (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
});
// 予約状況のライブ更新
window.Echo.private(`reservations.${reservationId}`)
    .listen('.reservation.status.updated', (event) => {
        console.log('予約ステータス更新:', event.status);

        // DOM更新
        const statusEl = document.getElementById('reservation-status');
        if (statusEl) {
            statusEl.textContent = getStatusLabel(event.status);
            statusEl.className   = `status-badge status-${event.status}`;
        }

        // トースト通知
        showToast(`予約ステータスが「${getStatusLabel(event.status)}」に更新されました`);
    });

// 管理者ダッシュボード
window.Echo.private('admin.reservations')
    .listen('.reservation.status.updated', (event) => {
        // 管理者向けリアルタイム更新
        updateAdminDashboard(event);
    });

Reverbサーバーの起動

# 開発環境
php artisan reverb:start

# デバッグモード
php artisan reverb:start --debug

# 本番環境(Supervisorで常時起動)
; /etc/supervisor/conf.d/reverb.conf
[program:reverb]
command=php /var/www/html/artisan reverb:start --host=0.0.0.0 --port=8080
autostart=true
autorestart=true
user=www-data

まとめ

Laravel Reverbにより、外部サービスへの依存なしに自前のWebSocket機能を低コストで実装できます。予約システム・チャット・リアルタイム在庫管理など、ライブ更新が必要な機能に最適です。弊社では予約管理システムのリアルタイム更新をReverbで実装しています。

LaravelによるWebシステム開発のご相談はお気軽にどうぞ。

Category 技術ブログ

Related Posts

関連記事

開発・技術のご相談はお気軽に

お見積りは無料です。まずはお気軽にご相談ください。

お問い合わせ →