見出し画像

【Laravel】リアルタイムのチャットを実装💬

LaravelのBroadcast、Pusher、およびLaravel Echoを使用することで、リアルタイムなチャット機能を簡単に実装することができます。この記事では、セットアップからチャット機能の実装、その後の機能拡張までの手順を解説します。ご自身のWebサービスでユーザーとのリアルタイムなコミュニケーションを実現したい方は是非参考にしてみてください。

1. はじめに

Webアプリケーションにリアルタイムなチャット機能を組み込む際、まず第一にサードパーティ製の便利なチャットbotツールが考えられます。ですが、既存システムとのデータ連携などの点から独自にチャットを実装する必要が出てくる場合もあると思います。
今回は、Laravel Broadcastを使用してリアルタイムなチャット機能を簡単に組み込む方法を紹介します。

完成イメージは↓のような感じです。(フロントエンドの実装は省略します)

チャット画面の完成イメージ

2. 使用する技術

Laravel Broadcast

Laravel公式サイト(ver10.x)のBroadcast解説はこちら↓。
https://readouble.com/laravel/10.x/ja/broadcasting.html

LaravelのBroadcastは、アプリケーション内で発生したイベントを非同期にブロードキャストするための機能です。これにより、イベントが発生したときに他のユーザーやクライアントに通知することができます。
Broadcastには3種類のチャンネルが存在します。

① Public
誰でもリッスンできる(オープンチャット)
② Private
認証済みのユーザーのみがリッスンできる
③ Presence
Privateの上位互換。チャンネルへのユーザーの参加や離脱もリッスンできる

今回はPublicチャンネルで実装しますが、特定のユーザーのみとのやりとりを実現するのであれば、PrivateまたはPresenceチャンネルでの実装(認証)が必要になります。

Pusher

Pusherは、リアルタイムのWebアプリケーションを構築するためのホステッドサービスです。Pusherを使用すると、ブラウザやモバイルデバイスとの間でリアルタイムのデータ同期を簡単に実現できます。LaravelのBroadcastはPusherをサポートしており、Pusherのアカウントを作成し、キーとシークレットを設定することで、PusherをLaravelプロジェクトで利用できます。

Laravel Echo

Laravel Echoは、クライアントサイドのJavaScriptライブラリであり、リアルタイムのイベント通知を受け取るためのインターフェースを提供します。Laravel Echoは、Pusherやその他のブロードキャストドライバと組み合わせて使用され、クライアントがサーバーからのイベントをリアルタイムに受け取り、反応することができます。Laravel Echoを使用すると、簡単にクライアント側のアプリケーションコードを記述し、リアルタイムな機能を実現できます。

ざっくりとした処理の流れは、以下のような感じです。

メッセージ送信(Aさん)

Laravel Broadcast ディスパッチ

Pusher

Laravel Echo リッスン(Bさん)

3. 実装

セットアップ

Laravelの設定

Broadcastを利用するために、Laravelの設定をしていきます。
config\app.php
// App\Providers\BroadcastServiceProvider::class,
↑のコメントアウトを外します。

.env
BROADCAST_DRIVER=pusher
.envのBroadcast Driverをpusherに設定します。デフォルトではlogになっているはずです。

Pusherの設定

まずはPusherをインストールします。
composer require pusher/pusher-php-server
Pusherのアカウント登録を済ませた後、App Keysに記載されている項目を.envに設定します。

PUSHER_APP_ID=PUSHERのapp_id
PUSHER_APP_KEY=PUSHERのkey
PUSHER_APP_SECRET=PUSHERのsecret
PUSHER_APP_CLUSTER=ap3

Laravel Echoの設定

必要なライブラリをインストールします。
npm install --save laravel-echo pusher-js

resources\js\bootstrap.jsを開いて、echoの設定をします。

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: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
  encrypted: true,
});

イベントの作成

メッセージ送信のイベントをartisanで作成します。
「メッセージが送信された」という意味なので、イベント名はMessageSentにしておきます。

% php artisan make:event MessageSent
Event [app/Events/MessageSent.php] created successfully.

Broadcastingを使用するために、MessageSentクラスでShouldBroadcastを継承します。

use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class MessageSent implements ShouldBroadcast
{
以下省略

メッセージ送信

送信するメッセージのオブジェクトとして、App\Library\Message.phpを作成します。

<?php

namespace App\Library;

class Message
{
    public $message_id;
    public $message;
}

先ほど作成したMessageSentイベントにbroadcastOnメソッドを設定します。

    /**
     * Get the channels the event should broadcast on.
     */
    public function broadcastOn(): Channel
    {
        return new Channel('testchat');
    }

クライアント側でメッセージを送信して、Controllerでイベントをディスパッチします。

$message = new Message;
$message->message_id = $request->message_id;
$message->message    = $request->message;

broadcast(new MessageSent($message))->toOthers();

※送信側ではJSでメッセージをレンダリングしている想定なので、toOthersで他者にのみディスパッチしています。

メッセージ受信(イベントリッスン)

window.Echo.channel('testchat').listen('MessageSent', (e) =>
{
  console.log(e.message);
	// メッセージをレンダリング
});
受信したメッセージの内容

e.messageの中に受信したメッセージオブジェクトが入っていることを確認できるはずです。あとはJavaScriptでメッセージをレンダリングしてあげれば完成です。

💡Tips

開発中はPusherのログをコンソール出力するように設定した方がやりやすいです。
本番ビルド時は出力しないように設定するのをお忘れなく!
resources\js\bootstrap.js

window.Pusher.logToConsole = true;

4. 機能拡張とカスタマイズ

今回はシンプルなメッセージの送受信のみを実装しましたが、実際のケースではもう少し多機能にする必要があるかもしれません。
以下、追加機能とその実装方法を例示します。

ファイルのアップロード

メッセージ送信と同じ経路を使って実現できます。
例えば、App\Library\Message.phpのプロパティにis_fileフラグやfilenameを追加して、ファイル送信の場合はこのプロパティに該当するデータを送信するようにします。メッセージ送信の際に、storage配下にファイルを保存して、受信側ではこれを参照します。

未読 / 既読の判定

presenceチャンネルを使って簡単に実現できます。
presenceチャンネルの場合、joiningイベント(ユーザーの参加)やleavingイベント(ユーザーの離脱)をリッスンできるので、これを使用して実現します。

~ 省略 ~
    .joining((user) => {
		// ユーザー参加
    })
	  .leaving((user) => {
		// ユーザー離脱
    })
~ 省略 ~

💡Tips

PrivateやPresenceチャンネルを利用する際にPusherからリッスンできない場合、認証エラーが考えられます。
BroadcastはデフォルトでLaravelの認証($request->user())を使用しているので、独自に認証を実装している場合は別途、bootstrap.jsに認証のエンドポイントを用意してあげる必要があります。

メッセージ削除

基本的にはメッセージ送信と同じ要領で、メッセージ削除のイベント(MessageDelete)を作成します。
Laravel Echoで削除イベントをリッスンして該当する要素を削除します。

~ 省略 ~
    .listen('MessageDeleted', (e) => {
		// メッセージ削除
    })
~ 省略 ~

5. まとめ

LaravelのBroadcast、Pusher、およびLaravel Echoを使用することで、リアルタイムなチャット機能を簡単に実装することができます。この記事では、セットアップからチャット機能の実装、さらなる拡張までの手順を解説しました。これにより、ユーザー間でのリアルタイムなコミュニケーションを実現する魅力的なアプリケーションを開発することができます。是非、ご自身のLaravelプロジェクトにリアルタイムチャット機能を追加してみてください。

プラスジャム製作開発部メンバーがWeb制作技術を紹介。
案件で実装した機能や自己学習で得た知識を発信していきます。
[今回の記事担当]バックエンドエンジニア k.m