Laravelのイベントをブロードキャストする

# #Laravel イベントをブロードキャストする

- Laravel 8.9.0
- Docker 19.03.12

----------

## イベントの作成

まずはプロジェクトを用意する。

```
laravel new chat-server && cd $_
```

`BroadcastServiceProvider` をコメントインして有効にする。

```
code config/app.php
```

```
// ...
App\Providers\BroadcastServiceProvider::class,
// ..
```

適当なイベントを作る。

```
php artisan make:event MessageReceived
```

```php
class MessageReceived implements ShouldBroadcast
{
    // ...
    public function broadcastOn()
    {
        return new Channel('test');
    }

    public function broadcastWith()
    {
        return [
            'message' => 'hello broadcast',
        ];
    }
}
```


## 動作確認

メッセージを発行してみる。

```
php artisan tinker
```

```
broadcast(new App\Events\MessageReceived());
```

デフォルトの `BROADCAST_DRIVER=log` なら `storage/logs/laravel.log` に書き込まれる。


## Redis

Pub/Sub サーバーとして Redis をセットアップする。

```
code docker-compose.yml
```

```yaml

version: "3"
services:
  redis:
    container_name: chat_redis_1
    image: redis:latest
    ports:
      - 6379:6379
```

```
docker-compose up -d
```

Redis クライアントを導入する。

```
composer require predis/predis
```

デフォルトは phpredis なので predis/predis を使うように切り替える。

```
code .env
```

```
REDIS_CLIENT=predis
```

Redis を使ってブロードキャストするように設定する。

```
code .env
```

```
BROADCAST_DRIVER=redis
```


## Laravel Echo Server

WebSocket サーバーとして Laravel Echo Server を導入する。

```
npm install laravel-echo-server
npx laravel-echo-server init
# ? Do you want to run this server in development mode? Yes
# ? Which port would you like to serve from? 6001
# ? Which database would you like to use to store presence channel members? redis
# ? Enter the host of your Laravel authentication server. http://localhost:8000
# ? Will you be serving on http or https? http
# ? Do you want to generate a client ID/Key for HTTP API? No
# ? Do you want to setup cross domain access to the API? No
# ? What do you want this config to be saved as? laravel-echo-server.json
```

development mode を有効にしておくとクライアントの接続やサーバーからのメッセージをコンソールに出力してくれる。


`config/database.php` の `redis.options.prefix` に合わせて、`databaseConfig.redis` に `keyPrefix` を設定する。

```
code laravel-echo-server.json
```

```
"keyPrefix": "laravel_database_"
```

```
code ~/chat/ws-server/package.json
```

```
"scripts": {
    "echo": "laravel-echo-server start",
    # ...
}
```


## Laravel Echo

クライアントもEchoで用意する。

```
npm i laravel-echo socket.io-client
```

```
code resources/js/bootstrap.js
```

```js
import Echo from "laravel-echo";

window.io = require("socket.io-client");

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


適当なリスナーを作る。

```
code resources/js/app.js
```

```js
// ...
window.Echo.channel("test").listen("MessageReceived", e => {
    console.info("Message received");
});
```

CSRFトークンのメタデータとJSアセットを読み込む。

```
code resources/views/welcome.blade.php
```

```html
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="csrf-token" content="{{ csrf_token() }}">
        <title>Laravel</title>
        <script src="{{ asset('js/app.js') }}" defer></script>
    </head>
    <body class="antialiased">
    </body>
</html>
```


## 動作確認

Laravel Echo Server と Laravel 本体を起動する。

```
npm run echo &
npm run dev
php artisan serve &
```

購読ページを開いて、コンソールを確認できる状態にする。

http://localhost:8000


Tinker からイベントを発行する。

```
php artisan tinker
```

```php
broadcast(new App\Events\MessageReceived());
```

初回がうまく送られないことがあるので、届かなかったら二度三度送ってみよう。

`{ message:` `"``hello broadcast``"` `}` を受け取れたら成功。


----------

https://readouble.com/laravel/8.x/ja/broadcasting.html

https://readouble.com/laravel/8.x/ja/redis.html


https://qiita.com/zaburo/items/34289d4573f39113b25a