18
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Laravelでソケット通信(Laravel WebSocket)

Last updated at Posted at 2023-08-29

Laravelでソケット通信をやってみます。

ソケット通信って?

主にリアルタイムなデータの送受信に使用されるもので、チャットアプリなどに用いられるものです。チャットアプリのメッセージは、画面を更新しなくても常に最新のものが表示されていきますよね。

おなじみのHTTP通信では、リクエストが送られたタイミングでレスポンスが返ってくるので、ユーザーが画面を更新しない限り最新の情報が表示されません。毎秒ごとにリクエストを発行する…というのは現実的ではないですよね。

そこで必要になるアプローチがソケット通信になります。
サーバーを常時監視し、アクションがあれば更新、といったことが可能になります。

Laravel WebSocketについて

ソケット通信を実装する一つの方法として、Pusherを用いる方法があります。Pusherでアカウントを作成して、Pusherサーバーを利用しての実装となります。
しかしなんと、Laravelは「Laravel WebSocket」により、自身でソケット通信を行うことが可能です。つまり、Pusherでアカウントを作成する必要はありません。Laravel自身がソケット通信のサーバーにもなるということです。

今回は、このLaravel WebSocketを用いて、Laravelでのソケット通信をやってみたいと思います。

やりたいこと

Laravel環境を2つ用意します。1つがバックエンド・1つがフロントという構成です。
バックエンド側のとあるアクションにPOSTされる度に、フロント側がリアルタイム(=画面更新なし)で表示を更新していく、というサンプルを作成します。

1.Dockerで環境作成

DockerでLaravel環境を2つ作成します。Dockerfileの内容など細かい部分は省きますので、ある程度お好みで作成して頂ければと思います。

バックエンド側

以下の要件を満たすLaravel環境を作成します。

  • DBが使える
  • ポート6001を許可する(ソケット通信がポート6001を使用するため)
docker-compose.yml
ports:
  - 8080:80
  - 6001:6001

フロント側

  • node及びnpmが使える

2.実装準備

dockerをビルド及び起動したら、まずは実装準備(composerなど)をします。

バックエンド側の実装準備

バックエンド側のコンテナに入り、下記でLaravelプロジェクトを作成

composer create-project laravel/laravel socket-test-back

socket-test-back/で、下記を実行

composer require beyondcode/laravel-websockets
composer require pusher/pusher-php-server "~3.0"
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
php artisan migrate

.envのPUSHER情報を編集 ※PUSHER_APP_ID、PUSHER_APP_KEY、PUSHER_APP_SECRETは任意の名前

.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=sampleId
PUSHER_APP_KEY=sampleKey
PUSHER_APP_SECRET=sampleSecret
PUSHER_APP_CLUSTER=mt1

config/broadcasting.phpの修正 ※Pusherの向き先を自身(localhost)にするイメージ

broadcasting.php
'pusher' => [
    'driver' => 'pusher',
    'key' => env('PUSHER_APP_KEY'),
    'secret' => env('PUSHER_APP_SECRET'),
    'app_id' => env('PUSHER_APP_ID'),
    'options' => [
        'cluster' => env('PUSHER_APP_CLUSTER'),
        'encrypted' => true,
        'useTLS' => false,
        'host' => 'localhost', 
        'port' => 6001,
        'scheme' => 'http', 
    ],
],

以上で、バックエンド側の実装準備は完了になります。

フロント側の実装準備

フロント側のコンテナに入り、下記でLaravelプロジェクトを作成

composer create-project laravel/laravel socket-test-front

必要なものをインストール

npm install pusher-js
npm install laravel-echo

resource/js/bootstrap.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: false,
    wsHost: 'localhost',
    wsPort: 6001,
});

.envのPUSHER情報を編集 ※PUSHER_APP_KEYとPUSHER_APP_CLUSTERをバックエンド側に合わせる

.env
PUSHER_APP_ID=
PUSHER_APP_KEY=sampleKey
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

npm起動

npm install
npm run dev

以上で、フロント側の実装準備は完了になります。

3.実装

ソケットを使用する準備は完了したので、実装していきます。

バックエンド側の実装

以下実行して、SampleEventとSampleControllerを作成

php artisan make:event SampleEvent
php artisan make:controller SampleController

修正する

SampleEvent.php
<?php

namespace App\Events;

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

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

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public $comment;
    
    public function __construct($comment)
    {
        $this->comment = $comment;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('sample-channel');
    }
}
SampleController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Events\SampleEvent;

class SampleController extends Controller
{
    public function fireChannel(Request $request)
    {
        SampleEvent::dispatch($request->comment);

        return response()->json(
            ["status" => 200]
        );
    }
}

routes/api.phpを修正

api.php
Route::controller(SampleController::class)->group(function () {
    Route::post('/sample/fire_channel', 'fireChannel');
});

これでバックエンド側の実装は完了しました。/sample/fire_channelにPOSTすることで、チャネルsample-channelにブロードキャストされます。

フロント側の実装

適当な画面を作成し、bladeを以下のように修正します。

index.blade.php
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>TEST</title>
    </head>
    <body>
        <div id="container"></div>
    </body>
    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script src="/js/app.js"></script>
    <script>
        {{-- チャンネルを監視 イベント検知すると処理実行 --}}
        window.Echo.channel('sample-channel')
            .listen('SampleEvent', (e) => {
                $("#container").append("<div>" + e.comment + "</div>");
            });
    </script>
</html>

これでフロント側の実装は完了しました。上記では、sample-channelにブロードキャストされる度に、POSTされたcommentを表示していくということをしています。

4.検証

バックエンド側で以下を実行し、ソケットサーバーを起動します。

php artisan websockets:serve

フロント側で作成した画面(ここでは/testにしてます)を開いた状態で、Postmanで/sample/fire_channelにPOSTしていきます。

ソケット検証.gif

ブラウザの画面更新なしで、情報が追加されていってますね!

まとめ

いかがでしたでしょうか?
今回はソケット通信を検証するためだけのサンプルとして、簡易にPOST値を表示するだけのものを作成しました。実際の開発では、イベント検知の度にDBを取得しにいって、リアルタイムで最新の情報を表示するといったことが多いかと思います。
ソケット通信を活用して、ユーザビリティ向上を図りましょう!

告知

最後にお知らせとなりますが、イーディーエーでは一緒に働くエンジニアを募集しております。

私は元々、自社開発企業にて開発を行っていましたが、自分の可能性を広げるべく、受託開発メインのイーディーエーに転職を決意しました。
イーディーエーに入社を決めた理由は、以下の3点です。
・多種多様な案件がある
・様々なことに挑戦できる
・かつフルリモートで勤務できる

様々な案件に挑戦し、スキルを身に付けたい。そしてフルリモートで仕事以外の時間も充実させたいという方は、ぜひ採用情報ページに足を運んでいただければと思います。
https://eda-inc.jp/recruit/
みなさまからのご応募をお待ちしております。

18
11
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
18
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?