前回の記事で、LaravelEchoを準備する方法について解説しました。
今回は、実際にLaravelEchoの処理をLaravelプロジェクト上に実装して動くようにしていきたいと思います。
まず、先日生成したlaravel-echo-server.jsonの内容を確認していきます。
下記のような内容になっていればOKです。違った内容や未入力の内容がある場合はjsonファイルを直接編集して修正します。
{
"authHost": "https://LaravelEchoServerが動作するサーバーのホスト名",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "省略(デフォルトで入ってます。)",
"key": "省略(デフォルトで入ってます。)"
}
],
"database": "redis",
"databaseConfig": {
"redis": {
"host" : "redisサーバーのipもしくはFQDN"
},
"sqlite": {
"databasePath": "databaseにsqliteを指定した場合はここにDBファイルのパスを入れる"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "https",
"socketio": {},
"secureOptions": 67108864,
"sslCertPath": "SSL証明書のパス",
"sslKeyPath": "SSL証明書秘密鍵のパス",
"sslCertChainPath": "SSL中間証明書のパス(必要であれば)",
"sslPassphrase": "SSL証明書秘密鍵のパスワード(必要であれば)",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "https://LaravelEchoServerが動作するサーバーのホスト名",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
laravel-echo-server.jsonはこれでOKです。
Laravel Echoのしくみを起動させる前に先に他の部分も設定していきます。
プロジェクトルート/config/app.phpの"Application Service Providers..."コメントの真下にあるブロック中の
//App\Providers\BroadcastServiceProvider::class,
のコメントアウトを外します。
App\Providers\BroadcastServiceProvider::class, //コメントアウトを外した状態
次に、.envを変更します。
設定値のうち、下記の2項目の値を”redis”に変えます。
BROADCAST_DRIVER=redis
QUEUE_CONNECTION=redis
.envの書き換えが終わったら、次のコマンドを実行します。
php artisan make:event PublicEvent
すると、プロジェクトルート/app/Events/にPublicEvent.phpが生成されます。
このファイルがWebsocketで送信するメッセージの設定内容になります。
broadcastOn()とbroadcastWith()を下記の例のように編集します。(日本語部分を任意のものに置き換えてください。)
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class PublicEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('通知のチャンネル名');
}
public function broadcastWith()
{
return [
'message' => 'ブラウザに送信するメッセージ',
];
}
}
上記のイベントファイルの記述が終わったら、コントローラー上のメッセージを送信させたい部分のところに、次のメソッドを入れます。(Controllerのルートはすでに記述済みとします。)
...省略...
use App\Events\PublicEvent;
...省略...
class HogeController extends Controller
{
public function photoStore(Request $request){
...省略※1...
event(new PublicEvent()); //ここで、さっきのプロジェクトルート/app/Events/PublicEvent.phpで指定したメッセージがブラウザに送信される。
...省略...
}
}
ここまで定義が終わったら、フロントエンド側でWebsocketに接続するためのロジックを記述します。
“プロジェクトルート/resources/js/app.js”もしくは”プロジェクトルート/resources/js/bootstrap.js”に次のコードを記述します。
//Websocket接続処理
import Echo from 'laravel-echo';
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: 'https://WebsocketサーバーのFQDN',
});
最後に、サーバーからWebsocket経由でメッセージを受け取ったときの処理を記述します。
window.Echo.channel('event-lib')
.listen('PublicEvent', (e) => {
//サーバーからWebsocket経由でメッセージが送られたときにさせたい処理。下記の一行は例。
alert('サーバーからのメッセージ', e.message);
})
//※実際は万が一接続が切れてしまった場合に、何らかのタイミング(ブラウザにフォーカスがあたったなどのイベント発生時やタイマーなど)で再接続を行うように上記のロジックを書く必要があります。
上記の処理は、app.js もしくは bootstrap.jsに記述すればサイト全体で反映されますし、特定のページのみで動作させたい場合は、各ページのみが参照するJavascriptに記述すればOKです。
ここまでできたら、実際に稼働させてみましょう。
プロジェクトルートにカレントディレクトリを移動し、次のコマンドを管理者権限で実行します。
laravel-echo-server start & php artisan queue:work
この状態で、最初に記述したコントローラーの ※1の処理が終わったあとでメッセージが表示され、アラートがブラウザ上に表示されればWebsocketの実装は成功です。
停止する場合はctrl+cを押したあとで、管理者権限で次のコマンドを入力します。
laravel-echo-server stop
お疲れさまでした…!