PHP
JavaScript
Redis
websocket
Laravel

人狼GM支援ツールを作る(Laravel Echo編)


はじめに

前回から間隔が空いてしまいましたが、この記事は人狼GM支援ツールを作る( Vue.js編)の続きとなります。

前回はVue.jsを使ってフロント側を作っていきました。

今回は、この「人狼GM支援ツール」の目玉であるチャット機能を実装します。

さて、今回のチャット機能はLaravel EchoというLaravelのプラグインを利用していきます。

このLaravel Echoがどういったものか、どう使うのかについて説明したいと思います。


Laravel Echoの使い方と設定


Laravel Echoとは

Laravel Echoとは……


Laravel EchoはJavaScriptライブラリで、チャンネルの購読とLaravelによるイベントブロードキャストのリッスンを苦労なしに実現してくれます。


だそうです。(日本語ドキュメントより抜粋)

一言で言えば、クライアント側での接続を助けてくれるやつってイメージですね。

npmで管理されているので、導入は以下のコマンドを叩くだけです。

npm install --save laravel-echo

websocketのブロードキャストにはpusherまたはredisが利用できます。

私はredisを利用したので、composerからPredisというライブラリをインストールした上で.envにredisを使うよう設定を追記しました。


websocketサーバの準備

redisを利用する場合には、socket.ioの実装が必要になります。

しかし、頑張って自力で実装する必要はありません。

なぜなら、laravel-echo-serverというLaravel用のsocket.io実装が用意されているからです。

こちらもnpmで管理されているので、以下のコマンドでインストールします。

npm install -g laravel-echo-server

その後、

laravel-echo-server init

で設定ファイルを作成し、

laravel-echo-server start

で起動します。

コンソール上にecho-serverが起動した旨の表示が出れば設定完了です。

以上、Laravelでwebsocketを利用するために必要なモジュールの紹介でした。

細かい設定などは省略しているので、自分で試す際はLaravelの日本語ドキュメントを参考にして進めるとよいでしょう。


redisとチャット機能の仕組み


redisとは

ところで、前の項目で


websocketのブロードキャストにはpusherまたはredisが利用できます。

私はredisを利用したので、composerからPredisというライブラリをインストールした上で.envにredisを使うよう設定を追記しました。


と書きました。

突然出てきたredisとはなにか、コイツを使うと何が嬉しいのか、という部分から解説していきます。

redisとは、いわゆるNoSQLデータベース(RDBMSでないデータベース)です。

key = value の形のデータをメモリ上に持ち、セッションストアやキャッシュストアなどに使われることが多いです。

今回の用途では、redisのDBとしての機能ではなく、publish/subscribeの機能を使います。

これは、「別クライアントから送信されたメッセージを受け取る」機能です。

redisに対して、

SUBSCRIBE <チャンネル名>

のコマンドを送ると、redisは受信待ちの状態になります。

この状態で、別のクライアントから

PUBLISH <チャンネル名> <内容>

のコマンドを送ると、SUBSCRIBEしているクライアントにメッセージが届きます。

この機能が、チャット機能のいわば橋渡しのような役割を担います。


Laravelからredisへ

次は、ブラウザ(javascript)から送信した文字がredisに送られるまでの流れを見ていきます。

javascript → Laravelは、Laravelで用意したチャットAPIにajaxで送りました。

送信した文字を受け取ったLaravel側では、「イベントブロードキャスト」という機能を使います。

簡単に言えば外部連携機能といったところでしょうか。

使い方は単純で、「redisに対してPUBLISHする」というイベントを用意しておくと、発火されたタイミングでredisにPUBLISHを送ります。

これでredisにユーザがブラウザ上で入力したチャット内容が到達しました!


redisからjavascriptへ

redisにPUBLISHしても、肝心のredisがSUBSCRIBEで受信待ちしていなければ意味がありませんね。

そこで、redisの状態からwebsocket接続までをよしなに管理してくれるスゴいヤツ、laravel-echo-serverの出番です。

本来なら自分でNode.jsを書く必要がある、redisの受信待ちや受け取ったメッセージをクライアントまで届けるといった部分を、

一手に担ってくれる優れものです。

laravel-echo-serverは以下のような役割を持ちます


  • laravel-echo-serverがredisを受信待ちにして、メッセージを待ち構える。

  • 同時に、クライアントとwebsocketの接続を行って、redisがメッセージをSUBSCRIBEしたらその内容をクライアントに流す。

つまり、redisからjavascriptまでの流れを全て担ってくれているわけですね。

これで、あるユーザが入力したチャット内容がLaravelとredis、laravel-echo-serverを介して別のユーザにリアルタイムで伝達されました。


いったん整理

ここまでの通信の流れを整理してみましょう。

クライアント

↓ HTTP

Webサーバ(Laravel)

↓ PUBLISH

redis

↓ SUBSCRIBE

laravel-echo-server

↓ websocket

クライアント

以上の流れで、私が実装したチャット機能は動いています。


実装とLaravel Mix


Laravel Mix

今まであまりLaravel Echoについて触れてこなかったわけですが、Laravel EchoとはJavaScriptライブラリなんですね。

つまり、フロント側に何かしらの手段で読み込ませる必要があるということになります。

ここで、LaravelとJavaScriptの橋渡しとなる最強ライブラリ、Laravel Mixの出番です。

これはwebpackのラッパーで、煩雑になりがちなビルドやバンドルの設定を少しのJavaScriptとPHPだけで記述できるというものです。

Laravel Echoを使いたい場合、Laravel MixならエントリポイントとなるJavaScriptに以下を記述するだけです。

import Echo from 'laravel-echo';

window.Echo = new Echo({
broadcaster: "socket.io",
host: window.location.hostname + ':6001'
});

laravel-echo-serverを使うためにbroadcaster: "socket.io"を指定し、

あとはlaravel-echo-serverのドメインを指定するだけで設定完了です。

Echoというプロパティをwindowに生やしているので、どこからでもLaravel Echoを呼び出せるようになりました。


Laravel Echoの使い方

前回まで、フロントからサーバ、redis、そしてlaravel-echo-serverへデータが流れるフローを解説しました。

残るはLaravel Echoを使ってlaravel-echo-serverからpushされるデータを受け取るだけです。

早速ですが、実装を見てみましょう。

Echo.channel('werewolves.' + roomId)

.listen('WerewolvesReceived', e => {
store.pushMessageList(e.message)
});

これは実際にフロントで書いたコードの一部となります(「人狼GM支援ツール」の一部なので、人狼だけが見れるチャットの部分ですね)

ブロードキャストするイベント内でどのチャンネルに飛ばすかを指定しているので、受け取る側では指定したチャンネルからどのイベントをリッスンするかを指定します。

laravel-echo-serverとブラウザはwebsocketで接続しているので、あとは受け取ったメッセージを画面に表示させるだけです。

駆け足気味な説明でしたが、ついにチャット機能が完成しました!


まとめ

今回はLaravel Echoでチャット機能を作ったお話でした。

「人狼GM支援ツールを作る」はこれで終わりとする予定ですが、また何かネタを思い出したら書くかもしれません。

ここまで読んでいただきまして、ありがとうございました。