はじめに
今回は、Webアプリケーションに欠かせないリアルタイム通知機能をテーマに、Laravelの強力な機能であるイベントとキュー、そしてブロードキャストを組み合わせて実装する方法を解説します。バックエンドにRedisを、フロントエンドにVue.jsとLaravel Echoを使うことで、シンプルながらも堅牢なシステムを構築します。
なぜリアルタイム通知にイベント駆動開発が適しているのか
リアルタイム通知は、ユーザーが何かアクションを起こしたとき(例: 誰かがあなたの投稿に「いいね」した)、関連するユーザーに即座に情報を伝える仕組みです。この種の機能には、イベント駆動開発が非常に適しています。
- 疎結合: ユーザーの「いいね」というアクション(イベント)と、通知を送信するというタスク(リスナー)が分離されるため、コードの依存関係が減り、保守性が向上します。
- 非同期処理: 通知処理はメインのリクエストとは切り離され、バックグラウンドで非同期に実行されます。これにより、ユーザーは通知処理が完了するのを待つことなく、すぐにレスポンスを受け取ることができ、パフォーマンスが向上します。
Laravelのイベント・キュー・ブロードキャスト機能の概要
- イベント: 特定の出来事(例: UserLikedPost)を表現するクラスです。
- リスナー: イベントが発生したときに実行されるタスク(例: 通知を生成し、送信する)を定義するクラスです。
- キュー: 時間のかかるタスクを非同期で実行するための仕組みです。リスナーをキューに登録することで、バックグラウンドで処理を実行できます。
- ブロードキャスト: リアルタイム通信を実現する機能です。サーバー側で発生したイベントを、WebSocket経由でクライアントに送信します。
本記事で構築するリアルタイム通知システムの全体像
本記事では、ユーザーが「いいね」ボタンをクリックすると、以下のフローでリアルタイム通知が送られるシステムを構築します。
- フロントエンド: ユーザーが「いいね」ボタンをクリックすると、APIリクエストが送信される。
- バックエンド: Laravelがリクエストを受け取り、PostLikedイベントを発火させる。
- キュー: PostLikedイベントに紐づいたリスナーがキューに登録される。
- Redis: キューに登録されたタスクがRedisに一時保存される。
- キューワーカー: キューワーカーがRedisからタスクを取り出し、通知を生成し、ブロードキャストイベントを発火させる。
- Laravel Echo Server: WebSocketサーバーがブロードキャストイベントを受け取り、フロントエンドに送信する。
- フロントエンド: Laravel EchoがWebSocket通信を受信し、Vue.jsがリアルタイムで通知を表示する。
開発環境のセットアップ
Docker Composeを使ったLaravelプロジェクトの準備
まず、Laravelプロジェクトと必要なサービス(Nginx、MySQL、Redis、Node.js)をDockerで動かすためのdocker-compose.ymlを作成します。
YAML
version: '3.8'
services:
app:
build:
context: ./
dockerfile: Dockerfile
volumes:
- .:/var/www/html
ports:
- "8000:8000"
networks:
- app-network
redis:
image: redis:6-alpine
ports:
- "6379:6379"
networks:
- app-network
# Laravel Echo Server用のNode.jsコンテナ
echo-server:
image: node:18-alpine
volumes:
- ./:/app
working_dir: /app
ports:
- "6001:6001"
command: sh -c "npm install && node laravel-echo-server.js start"
depends_on:
- redis
networks:
- app-network
networks:
app-network:
driver: bridge
echo-serverコンテナは、Node.jsベースのWebSocketサーバーであるlaravel-echo-serverを実行するために使用します。
RedisコンテナとLaravelのキュー設定
次に、LaravelがRedisをキューとして使用するように設定します。.envファイルを編集します。
QUEUE_CONNECTION=redis
REDIS_HOST=redis
これで、php artisan queue:workコマンドを実行すると、Redisからキューのタスクが処理されるようになります。
Node.jsとLaravel Echoの導入
フロントエンドでWebSocket通信を処理するために、Node.jsとlaravel-echo、socket.io-clientを導入します。
Bash
docker-compose exec app npm install laravel-echo socket.io-client --save-dev
2. イベントとリスナーの作成
ユーザー登録を例にしたイベントの定義
ここでは、「投稿にいいねがされた」というイベントを例にします。まず、PostLikedイベントクラスを作成します。
Bash
docker-compose exec app php artisan make:event PostLiked
app/Events/PostLiked.phpに、イベントのプロパティを定義します。
PHP
// app/Events/PostLiked.php
<?php
namespace App\Events;
//...
class PostLiked
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public $post;
public function __construct(User $user, Post $post)
{
$this->user = $user;
$this->post = $post;
}
//...
}
イベントをトリガーに通知を送信するリスナーの実装
次に、PostLikedイベントが発生したときに実行されるリスナーを作成します。
Bash
docker-compose exec app php artisan make:listener SendPostLikedNotification --event=PostLiked --queued
--queuedオプションを付けることで、このリスナーは非同期でキューを使って実行されるようになります。
app/Listeners/SendPostLikedNotification.phpのhandleメソッドに、通知送信ロジックを記述します。
PHP
// app/Listeners/SendPostLikedNotification.php
public function handle(PostLiked $event): void
{
$postOwner = $event->post->user;
$liker = $event->user;
$postOwner->notify(new PostLikedNotification($liker, $event->post));
}
最後に、イベントとリスナーを紐づけるために、app/Providers/EventServiceProvider.phpに登録します。
PHP
// app/Providers/EventServiceProvider.php
protected $listen = [
PostLiked::class => [
SendPostLikedNotification::class,
],
];
これで、「いいね」のアクションをトリガーに、非同期で通知が生成される仕組みができました。
キューを使った非同期処理のメリット
キューを使うことで、時間のかかる処理(通知の生成、メール送信、画像処理など)をバックグラウンドに回すことができます。これにより、HTTPリクエストの応答時間を短縮し、ユーザーエクスペリエンスを向上させます。また、キューワーカーを複数起動することで、処理能力をスケールさせることも可能です。
リアルタイムブロードキャストの実装
Laravelのブロードキャスト設定
通知をリアルタイムでフロントエンドに送信するために、ブロードキャスト機能を有効化します。
.envでBROADCAST_DRIVERをredisに設定し、config/broadcasting.phpでRedis接続を設定します。
BROADCAST_DRIVER=redis
REDIS_HOST=redis
次に、通知クラスにShouldBroadcastインターフェースを実装します。
PHP
// app/Notifications/PostLikedNotification.php
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class PostLikedNotification extends Notification implements ShouldBroadcast
{
// ...
}
ShouldBroadcastを実装することで、この通知がイベントとしてブロードキャストされるようになります。
Redisとlaravel-echo-serverの連携
laravel-echo-serverは、Laravelのブロードキャスト機能とWebSocket通信を仲介するサーバーです。
laravel-echo-server.jsonファイルを作成します。
JSON
{
"authHost": "http://localhost:8000",
"authEndpoint": "/api/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {
"host": "redis",
"port": "6379"
}
},
"devMode": true,
"host": "0.0.0.0",
"port": "6001",
"protocol": "http"
}
この設定ファイルで、databaseConfigにRedisコンテナのホスト名(redis)とポート(6379)を指定します。authHostはLaravelアプリケーションのURLです。
Vue.jsを使ったフロントエンドでのリアルタイム通知の購読
最後に、フロントエンドでWebSocket通信をリッスンし、通知を受け取って表示するロジックを実装します。
JavaScript
// resources/js/app.js
import Echo from 'laravel-echo';
import io from 'socket.io-client';
window.io = io;
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
window.Echo.private(`App.Models.User.${userId}`)
.notification((notification) => {
console.log('リアルタイム通知:', notification.message);
// ここで通知を画面に表示するロジックを実装
});
このコードは、App.Models.User.{userId}というプライベートチャンネルを購読し、通知が届くとnotificationコールバックが実行されます。
まとめと応用
構築したリアルタイム通知システムのレビュー
本記事で構築したシステムは、以下の特徴を持っています。
- 非同期: キューを使って時間のかかる処理をバックグラウンドで実行。
- リアルタイム: WebSocket通信により、即座に通知を送信。
- スケーラブル: Redisとキューワーカーを組み合わせることで、トラフィックが増加しても容易にスケールアウト可能。
通知の永続化と未読管理の追加
このシステムはリアルタイム通知を実装していますが、通知をデータベースに保存し、ユーザーがいつでも確認できるようにすることも重要です。LaravelのNotifications機能は、この永続化と未読管理の機能も提供しています。
- 永続化: databaseドライバを使って通知をデータベースに保存。
- 未読管理: markAsRead()メソッドを使って通知を既読にすることができます。
さらなるスケールを見据えたアーキテクチャの検討
本番環境では、laravel-echo-serverの代わりに、より堅牢なプッシャーサービス(例: PusherやLaravel Reverb)を使用することが推奨されます。これらのサービスは、WebSocketサーバーの運用を管理してくれるため、開発者はアプリケーションロジックに集中できます。
今回の記事では、LaravelとRedisを使ったイベント駆動のリアルタイム通知システムを、Docker環境で構築する方法を解説しました。この知識を活かし、あなたのアプリケーションにユーザーエンゲージメントを高める機能をぜひ実装してみてください。
安心安全のホワイト高還元SESに転職を考えている方へ
新しい挑戦に踏み出すことは、人生において重要な一歩です。 転職活動は自分自身を知り、成長する貴重な機会でもあり、夢や成長を追求するためには必要な要素の一つ になるかと思います。 どんな選択をされるにせよ、その決断があなたに取って素晴らしい未来を切り開くことを願っています! グラディートと一緒に誇れるエンジニアを目指しましょう!
■『株式会社グラディート』では受託開発・SES・ブランディングデザイン・事業コンサルティングなどを事業として行う都内のIT企業です。現在、不遇な待遇で困っているエンジニアさんは、ぜひ一度グラディートに相談してみてね!(年収査定・SESへの転職相談も承っております!)
株式会社グラディート採用情報はこちら▼
https://en-gage.net/gradito/
株式会社グラディート公式サイトはこちら▼
https://www.gradito.co.jp/