LoginSignup
0
0

More than 1 year has passed since last update.

さくらVPS(Rocky Linux) + laravel + Inetria(vue3)でbroadcastの実装メモ

Last updated at Posted at 2022-07-29

laravel broadcastの使いどころ

一般的なクライアントサーバの仕組みは
クライアントからの要求に対してサーバが応答を返す流れとなる。

サーバ側からクライアント側への逆方向のイベントがないので
サーバ内で発生した変更を知るにはクライントがサーバに対して
定期ポーリングするなどの仕組みが必要だった。

laravelフレームワークではbroadcastという仕組みが用意されており。
websocketサーバを介してサーバからのリアルタイムの変更通知を受信することができる。

前提となる知識としては
backend(laravel)側はLaravelのイベント、リスナー、キューワーカーの知識
frontend(jsvascript)ではWebsocketの知識が前提となる。

Websocketサーバによる外部サービスとしてPusher、ablyなどの無料プランが使えるが
laravel-echoやlaravel-websocketsなどのlaravelフレームワークが用意した
websocketサーバを自前で用意してもよい。その場合はwebscoketサーバの構築の知識が必要になる。

まずは外部サービスpusherjsで実装してみる

pusherjsにてアカウント作成してAPP_KEYを発行する

app_id = "XXXXXX"
key = "yyyyyyyyyyyyyyyyyyyyyy"
secret = "zzzzzzzzzzzzzzzzzz"
cluster = "ap3" // pusherサーバのtimezoneらしい

この値をコピーして.envファイルのPUSHER関連の値を設定する

# BROADCAST_DRIVER=log
BROADCAST_DRIVER=pusherjs
()
PUSHER_APP_ID=XXXXXX
PUSHER_APP_KEY=yyyyyyyyyyyyyyyyyyyyyy
PUSHER_APP_SECRET=zzzzzzzzzzzzzzzzzz
PUSHER_APP_CLUSTER=ap3

※以下、websocketサーバ(socketi,laravel-websockets)を自前で用意する場合

WSサーバ構築

laravel(backendとfront)側の設定

laravel(backend)からfrontend(javascript)への橋渡しのライブラリをインストールする。

$ composer require inertiajs/inertia-laravel

front側にinertiaとvueライブラリをインストールする。

$ npm install @inertiajs/inertia @inertiajs/inertia-vue3

front側の大本のファイルは唯一のbladeファイルであるresources/views/app.blade.phpとなる。
vueファイルの大本はresources/js/app.js
各画面のvueコンポーネントはresources/js/Pages/配下にvueファイルを格納する構成となる

一覧画面とチャット送信のアクションだけのシンプルなIFのみとする。
一覧画面のURLは/chat。メッセージの一覧を取得し、画面側に表示する。
送信ボタンでメッセージを登録する。
ここでイベントを使い、同じ画面を見ている別の端末に通知を受信するようにする。

ルーティングは以下の2つ。

routes\web.php
Route::get('/chat', 'ChatController@index');
Route::post('/chat', 'ChatController@store');

コントローラでInetriaライブラリつかってページにルーティングする。

app\Http\Controller\ChatController.php
()
class ChatController extends Controller
{
    public function index()
    {
        return Inertia::render('Chat/Index', [
           'messages' => Message::all([
               'body', 'created_at'
           ]);
        ]);
    }
    public function store(Request $request)
    {
        $message = Message::create([
            'body' => $request->message,
        ]);
        /* 通知用のイベントをキューに積む */
        event(new MessagePostAppended($message));
        return redirect()->route('chat.index');
    }
}
()

MessagePostAppendedがないのでイベントを作成

$ php artisan make:event MessagePostAppended

broadcast機能を使うのでShouldBroadcastを継承させる。

app\Events\MessagePostAppended
()
class MessagePostAppended implements ShouldBroadcast
{
    public $message;
    public function __construct(Message $message)
    {
        $this->message = $message;
    }
    public function broadcastOn()
    {
        return new Channel('my-channel');
    }
    public function broadcastAs()
    {
        return 'message.appended';
    }
}

broadcastOnが初期値だとPrivateChannelになっているのでChannelクラスに変更。
broadcastAsでイベント名を任意に設定できる。ない場合はクラス名MessagePostAppended
となる。

このmy-channelmessage.appended(MessagePostAppended)をfront側で使用する。

front側のjsパッケージをインストールする。

$ npm install --save laravel-echo pusher-js

pusher-jsはpusherjsが提供しているwebsocketライブラリ、
laravel-echoはlaravelが提供しているWebSocketライブラリで
自前でwebsocket(laravel-echo-serverとかsocket-io)を構築する場合はこちらを利用する。
broadcastの指定でpusherjsもサポートしています。要pusher-js

bootsrrap.jsでlaravel-echoインスタンスを生成する。
pusherライブラリもグローバルのPusherでロードし使えるようにしておく。

resources\js\bootstrap.js
()
import Echo from 'laravel-echo';

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    forceTLS: true,
});

front側はresources\js\Pages\Chat\Index.vueを作成
broadcastのメッセージを受信したらreloadするようにする
listenメソッドのイベントの名称は
クラス名の場合はそのままクラス名だがbroadcastAsで別名を指定した場合は
先頭にピリオドをつけて.message.appendedで待ち受ける。

resources\js\Pages\Chat\Index.vue
<script setup>
import { ref } from 'vue';
import BreezeAuthenticatedLayout from '@/Layouts/Authenticated.vue';
import BreezeButton from '@/Components/Button.vue';
import { Inertia } from '@inertiajs/inertia';
import { Head, Link, useForm } from '@inertiajs/inertia-vue3';

defineProps({
    messages: Array,
});

const submit = () => {
    form.post(route('chat.store'), {
        onFinish: () => {
          form.reset();
          form.message = '';          
        },
    });
};

Echo.channel('my-channel')
.listen('.message.appended', (e) => {
  console.log(e);
  Inertia.reload();
});
</script>
<template>
  <h1>タイトル</h1>
  <div v-for="msg in messages">
    <span v-text="msg.created_at"></span>&nbsp;
    <span v-text="msg.body"></span>
  </div>
  <form @submit.prevent="submit">
    <textarea v-model="form.message"></textarea><br>
     <BreezeButton class="ml-4" :disabled="form.processing">送信</BreezeButton>
  </form>
</template>

ここまででWebscoketを外部サービスであるPusherで実装した。
次はこちらをベースに代替フリーウェアのlaravel-websocketsを使用して
ブロードキャスト機能を実装する。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0