Laravel Echo (Websocket ブロードキャスト)を試す

最近PHPフレームワークを触る機会が増えて、RailsのActionCableみたいなことがLaravelのEcho(ブロードキャスト 6.x Laravel)で実現できるらしいと興味を持ったので試してみた。

だいたい下記記事の通りだけど、一部記載の通りでは動作しなかったところもあるので捕捉的にで実現できるらしいと興味を持ったので試してみた。

 

だいたい下記記事の通りだけど、一部記載の通りでは動作しなかったり躓いたところもあるので捕捉として、Laravel初心者なので環境の構築からメモを残す。お試しのVbox上構築なので、セキュリティ対策とかそんな吟味してないので気を付けて!

qiita.com

 

長いのでまとめると

  • チャンネル購読するにはクライアント側でチャンネル名にRedisのprefix(laravel_database_)を足す必要があった。
  • ポート開放(firewall-cmd)忘れずに。
  • laravel-echo-server start でエラーでたら下記コマンドで直った。

sudo npm install n -g
sudo n latest

 

環境

  • CentOS 7
  • VirtualBox ネットワークはブリッジアダプタ(ipは 192.168.0.100 とする)
  • PHP 7.3
  • Laravel Framework 6.6.0
  • Apache/2.4.6
  • mariadb-server
  • Redis

 「larapro」が今回のテスト用のlaravelプロジェクト名です

ユーザー名は「centuser」ということにします。

構築

sudo yum install epel-release
sudo rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

sudo yum -y install --enablerepo=remi,remi-php73 php php-devel php-mbstring php-pdo php-gd php-xml php-mcrypt
sudo yum -y install --enablerepo=remi,remi-php73 php-opcache php-mysqlnd
sudo yum -y install --enablerepo=remi,remi-php73 composer
sudo yum -y install --enablerepo=remi,remi-php73 php-pecl-redis

 

 

DB周り

sudo yum install mariadb mariadb-server mariadb-client
sudo vi /etc/my.cnf

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[mysqldump]
default-character-set=utf8mb4

[mysqld]
character-set-server=utf8mb4

sudo systemctl start mariadb
sudo systemctl enable mariadb
sudo mysql_secure_installation

mysql -u root -p

 文字コードの確認  UTF8mb4になってればOK

MariaDB [(none)]> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |

  • | character_sets_dir | /usr/share/mysql/charsets/ |

+--------------------------+----------------------------+

適当にデータベースを用意する

MariaDB [(none)]> CREATE DATABASE test_laravel;

 

Apache httpd周り

sudo mkdir /var/www/project

sudo chmod 2775 /var/www/project/

sudo chown apache:apache /var/www/project/

sudo usermod -aG apache centuser

sudo vi /etc/httpd/conf/httpd.conf

 Vbox上でIPアクセスするのでバーチャルホストではなくDocuRoot直接設定しちゃう

DocumentRoot "/var/www/project/larapro/public"

<Directory "/var/www">
AllowOverride None
Require all granted
</Directory>
<Directory "/var/www/project">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>

 sudo systemctl restart httpd

sudo systemctl enable httpd

 

Redis

sudo yum install redis

sudo systemctl enable redis
sudo systemctl start redis

redis-cli

 

Firewall ポート開放

sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-port=6001/tcp --permanent
sudo firewall-cmd --reload

Laravel構築

cd /var/www/project/

composer create-project --prefer-dist laravel/laravel larapro

cd larapro

npm install --save laravel-echo socket.io-client

composer require predis/predis

npm install -g laravel-echo-server

laravel-echo-server init

 こんな感じで対話形式でLaravel Echoの設定する

 192.168.0.100 のところは各々の環境のアドレスを設定してください

? 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://192.168.0.100
? Will you be serving on http or https? http
? Do you want to generate a client ID/Key for HTTP API? Yes
? Do you want to setup cross domain access to the API? Yes
? Specify the URI that may access the API: http://192.168.0.100:80
? Enter the HTTP methods that are allowed for CORS: GET, POST
? Enter the HTTP headers that are allowed for CORS: Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorizat
ion, X-CSRF-TOKEN, X-Socket-Id
? What do you want this config to be saved as? laravel-echo-server.json
appId: xxxxxxxxxxxxxxxx
key: 01010101010101010101010101010101
Configuration file saved. Run laravel-echo-server start to run server.

sudo laravel-echo-server start

 ※もし

Starting server in DEV mode...

/usr/lib/node_modules/laravel-echo-server/node_modules/ws/lib/websocket.js:347
...options
^^^

  というエラーがでたら

sudo npm install n -g
sudo n latest

 を実行しよう

 

ここから先はだいたい参考記事(https://qiita.com/zaburo/items/34289d4573f39113b25a)と同じ

ディレクトリは引き続きプロジェクトルート(/var/www/project/larapro)にて

vi config/app.php

vi .env

php artisan make:event PublicEvent

vi ./app/Events/PublicEvent.php

<?php

namespace App\Events;

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

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

    /**
    * Create a new event instance.
    *
    * @return void
    */
    public function __construct()
    {
    //
    }

    /**
    * Get the channels the event should broadcast on.
    *
    * @return \Illuminate\Broadcasting\Channel|array
    */
    public function broadcastOn()
    {
        return new Channel('hoge-channel');
        // return new PrivateChannel('channel-name');
    }
    public function broadcastWith()
    {
        return [
            'message' => 'PUBLIC',
            ];
    }
}

vi ./routes/web.php 

 ここでは「/fire」にアクセスしたらEvent発火させることにした

Route::get('/', function () {
    return view('welcome');
});

Route::get('/fire', function(){
    broadcast(new \App\Events\PublicEvent);
    return 'public';
});

vi ./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'
});

//購読するチャネルの設定
window.Echo.channel('laravel_database_hoge-channel')
    .listen('PublicEvent', (e) => {
    console.log(e);
});

  ※余談ハマった点

window.Echo.channel('laravel_database_hoge-channel')

  購読チャンネル名は「hoge-channel」だが、それに加えて「laravel_database」をprefixとして頭に付け加えなければならなかった。

 prefixがどこで設定されているかというと「./config/database.php」のこのあたり

'redis' => [

'client' => env('REDIS_CLIENT', 'phpredis'),

'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],

 

npm run dev

vi ./resources/views/welcome.blade.php

 <head>内に挿入

<meta name="csrf-token" content="{{ csrf_token() }}">

 <body>タグ最後に挿入

 <script src="{{ asset('js/app.js')}}"></script>

 

あとは参考記事(https://qiita.com/zaburo/items/34289d4573f39113b25a)と同じように、「http://192.168.0.100/」でコンソールを開いておいて「http://192.168.0.100/fire」を開いたらコンソールにPUBLICと表示されたら成功

 

おしまい

 

プライベートチャンネルは必要になったらまた試すかも

でもあとは参考記事と同じで大丈夫だと思う

 

重ねて感謝

qiita.com