【Laravel】Pusherを使ってリアルタイムにイベントを更新する


今回作るもの

こちらのチュートリアルを参考に、サーバで発行したイベントの結果をリアルタイムにチャートで表現します。

JavaScript realtime chart quick start

環境

PHP: 7.2.5
Laravel: 7.0
pusher-php-server: 4.1

Pusher Appの作成

こちらの記事を参考にAppを作成してください。

チャートページの作成

チュートリアルのページを参考(ほぼコピペ)にGoogle Chartsを使用してチャートUIを作成します。

resources/views/realtime-chart.blade.php
<html>
    <body>
        <div id="chart_div" style="width: 100%; height: 500px;"></div>
        <script src="https://www.gstatic.com/charts/loader.js"></script>
        <script src="https://js.pusher.com/5.1/pusher.min.js"></script>
        <script>
            google.charts.load('current', {'packages': ['corechart']});
            google.charts.setOnLoadCallback(() => {
                // Instead of hard-coding the initial table data,
                // you could fetch it from your server.
                const dataTable = google.visualization.arrayToDataTable([
                    ['Year', 'Price'],
                    [2013, 400],
                    [2014, 460],
                ]);
                const chart = new google.visualization.AreaChart(
                    document.getElementById('chart_div'));
                const options = {
                    title: '1 BTC in USD',
                    hAxis: {title: 'Year', titleTextStyle: {color: '#333'}},
                    vAxis: {minValue: 0},
                    animation: {duration: 100, easing: 'out'}
                };
                chart.draw(dataTable, options);
                let year = 2015;
                Pusher.logToConsole = true;
                const pusher = new Pusher("{{ config('const.pusher.app_key') }}", { // Replace with 'key' from dashboard
                    cluster: "{{ config('const.pusher.cluster') }}",              // Replace with 'cluster' from dashboard
                    forceTLS: true
                });
                const channel = pusher.subscribe('price-btcusd');
                channel.bind('new-price', data => {
                    const row = [year++, data.value];
                    dataTable.addRow(row);
                    chart.draw(dataTable, options);
                });
            });
        </script>
    </body>
</html>

この時Pusherの引数に直接APP_KEYAPP_CLUSTERの値を入れずに定数などを作成するようにしましょう。

このページではprice-btcusdチャンネルのnew-priceイベントを待機しています。
イベントが発生するとvalueフィールドが抽出され、新しいデータとしてグラフに追加されます。

最後にこのページへのルーティングを設定すれば完了です。

routes/web.php
Route::get('/realtime-chart', function () {
    return view('realtime-chart');
});

サーバーからイベントを発行する

イベントを受け取るページを作成したので、今度はイベントを発行する処理を作成しましょう。

まずPusherのライブラリを追加します。

composer require pusher/pusher-php-server

.envにPusherアプリの設定を記載します。
アプリのキーはGetting Startedのサンプル内、またはApp Keysタブに記載されているのでそちらを参照してください。

.env
PUSHER_APP_ID=12345
PUSHER_APP_KEY=hoge-app-key
PUSHER_APP_SECRET=hoge-app-secret
PUSHER_APP_CLUSTER=hoge-cluster

またこれを呼び出すための定数を作成します。

config/const.php
return [
    'pusher' => [
        'app_id' => env('PUSHER_APP_ID'),
        'app_key' => env('PUSHER_APP_KEY'),
        'app_secret' => env('PUSHER_APP_SECRET'),
        'cluster' => env('PUSHER_APP_CLUSTER'),
    ]
];

config/app.phpPusherを追加します。

config/app.php
return [
    ...
    'aliases' => [
        ...
        'Pusher' => Pusher\Pusher::class,
    ]
]

実際にイベントを発行する処理を実装します。

namespace App;

use Pusher\Pusher;

class RealtimeChartEvent
{
    public function run()
    {
        $pusher = new Pusher(
            config('const.pusher.app_key'),
            config('const.pusher.app_secret'),
            config('const.pusher.app_id'),
            array(
                'cluster' => config('const.pusher.cluster')
            )
        );

        $i = 0;

        // 毎秒新しいランダムな値をvalueに含めたイベントを発行する
        // 実際に使用する場合は毎秒では無く、データの変更をトリガーにしてイベントを発行してください
        while (true) {
            $pusher->trigger('price-btcusd', 'new-price', array(
                'value' => rand(0, 5000)
            ));

            // 何回イベントを発行したかを確認するために追加
            $i ++;
            echo('send ' . $i . ' times' . PHP_EOL);

            sleep(1);
        }
    }
}

動作確認

  • 作成したチャートのページを開きます。(http://localhost:10080/realtime-chart)

  • tinkerを開き、先ほど作成したイベントを実行します。(永久ループするので終了する場合はcontrol + c)

$ php artisan tinker

>>> $event = new App\Events\RealtimeChartEvent();
>>> $event->run();
  • 実行ログが流れ、チャートがリアルタイムに動作したら成功です。

send 1 times
send 2 times
send 3 times
send 4 times
send 5 times
...

Pusherのダッシュボードでイベントを確認

PusherのダッシュボードからChannels→アプリを選択→Overviewを開くと、作成したAppにどれぐらいのconnectionとmessageが送られたかを確認することができます。

参考資料

JavaScript realtime chart quick start
【Laravel】Pusherを使ってみる
Pusher公式ドキュメント
Class 'Pusher\Pusher' not found #26