【Laravel】Pusherを使ってみる

# 環境
PHP: 7.2.5
Laravel: 7.0
pusher-php-server: 4.1

# PusherでAppを作成する

まずは[Pusher](https://pusher.com/)にアカウントを作成しましょう。

ログインすると新規にChannels Appを作成する画面へと遷移します。

<img width="783" alt="スクリーンショット 2020-06-13 22.34.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/65823b1e-9287-b5f7-ce72-00aca534170f.png">

* アプリ名の入力欄の下の`create apps for multiple environments`を選択すると、development, staging, productionの三つの環境のアプリを同時に作成することができます。
* clusterは特に理由がなければap3(東京リージョン)を選択しましょう。
* front-end techとback-end techはどれでも大丈夫です。
    * チュートリアルで表示される言語が選択したものになるだけです。
    * 今回はback-end techにLaravelを選択しました。

# LaravelでPublic Channelを試してみる

アプリを作成したら最初に遷移するページにあるGetting StartedをLaravelのみを使用して試してみます。

## Step1 イベント受信ページの作成。

まずは`my-channel`の`my-event`というイベントを受け取るページを作成します。

Getting StartedにあるStep1で`Javascript`を選択します。

そこに書いてある`index.html`をLaravelのviewに作成します。

```html:resources/views/pusher-index.blade.php
<!DOCTYPE html>
<head>
    <title>Pusher Test</title>
    <script src="https://js.pusher.com/6.0/pusher.min.js"></script>
    <script>

        // Enable pusher logging - don't include this in production
        Pusher.logToConsole = true;

        var pusher = new Pusher("{{ config('const.pusher.app_key') }}", {
            cluster: "{{ config('const.pusher.cluster') }}"
        });

        var channel = pusher.subscribe('my-channel');
        channel.bind('my-event', function(data) {
            alert(JSON.stringify(data));
        });
    </script>
</head>
<body>
<h1>Pusher Test</h1>
<p>
    Try publishing an event to channel <code>my-channel</code>
    with event name <code>my-event</code>.
</p>
</body>
```

この時app_keyの情報やclusterの情報をそのまま書き込むのは危険なので、定数として抜き出しましょう。

```php:config/const.php
return [
    'pusher' => [
        'app_key' => env('PUSHER_APP_KEY'),
        'cluster' => env('PUSHER_APP_CLUSTER'),
    ]
];
```

bladeを作成したらルーティングを設定します。

```php:routes/web.php
Route::group(['prefix' => '/pusher'], function () {
    Route::get('/index', function () {
        return view('pusher-index');
    });
});
```

これでイベントを受け取るページが完成しました。
http://localhost:10080/pusher/index

<img width="716" alt="スクリーンショット 2020-06-14 11.53.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/db9e6eaf-5beb-f63e-188c-c9ee980c5ef1.png">

## Step2 イベント送信用エンドポイントの作成

次はイベントを発行するエンドポイントを作成します。

まずは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
```

`broadcasting.php`を書き換えます。（Laravel7では既に設定されているため必要ありません。）

```php:config/broadcasting.php
return [
    ...
    'connections' => [
        'pusher' => [
            ...
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'useTLS' => true,
            ],
        ],
    ]
];
```

そうしたらイベントを発行するクラスを作成します。

```php:app/Events/MyEvent.php
namespace App\Events;

use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class MyEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    public function __construct($message)
    {
        $this->message = $message;
    }

    public function broadcastOn()
    {
        return ['my-channel'];
    }

    public function broadcastAs()
    {
        return 'my-event';
    }
}
```

最後にこのイベントを呼び出すエンドポイントを設定しましょう。

```php:routes/web.php
Route::group(['prefix' => '/pusher'], function () {
    Route::get('/index', function () {
        return view('pusher-index');
    });

    // 追加
    Route::get('/hello-world', function () {
        event(new App\Events\MyEvent('hello world'));
        return ['message' => 'send to message : hello world'];
    });
});
```

## 動作確認

実際に動作するか確認してみます。

1. イベントを受信するページを開きます。（http://localhost:10080/pusher/index）
2. ブラウザの別のタブでイベントを発行するページを開きます。（http://localhost:10080/pusher/hello-world）

<img width="342" alt="スクリーンショット 2020-06-14 12.17.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/274ebbd3-7aa6-897c-26d6-826a5dba6237.png">

3. 受信ページにメッセージが表示されれば成功です。

<img width="472" alt="スクリーンショット 2020-06-14 12.16.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/a6271081-0d7d-41b0-6a62-f3a090601f56.png">

## 参考資料
[Pusher公式ドキュメント](https://pusher.com/docs)
[Pusher で WebSocket 通信を試してみる](https://note.com/mkudo/n/nb21e64dc2f4c)