#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
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
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
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
// ...
window.Echo.channel("test").listen("MessageReceived", e => {
console.info("Message received");
});
CSRFトークンのメタデータとJSアセットを読み込む。
code resources/views/welcome.blade.php
<!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 &
購読ページを開いて、コンソールを確認できる状態にする。
Tinker からイベントを発行する。
php artisan tinker
broadcast(new App\Events\MessageReceived());
初回がうまく送られないことがあるので、届かなかったら二度三度送ってみよう。
{ message:
"``hello broadcast``"
}
を受け取れたら成功。