Laravel EchoとPusherでリアルタイムチャットを作ってみた。
こんにちは。
ニシザワです。
本日はLaravel EchoとPusherを使ってリアルタイムチャットが簡単にできたのでその方法を書きます。
まずは、こちらの登録をします。
次にCreate new appよりアプリを作成してください。
③は今回はなんでもいいですが、Vanilla Jsを選択
④はLaravelを選択
⑤は適当にコメントを入れていただいてCreate my appで作成してください。
今回は認証は入れませんが、入れたい場合はPrivateChannelを使います。
今回は認証など条件は必要ないので常にtrueを返しています。
.env
pusherのダッシュボード>App Keysにあるのでそちらから写します。
config/app.phpで
resources/assets/js/app.js
channel('post')のpostはrouteで定義したchannel名になります。
listen('Posted'のPostedはEventで定義したクラス名が入ります。
名前空間などが違う場合はEventで定義したクラスに別名をつけることも可能です。
ざっと説明しましたが、これで完了です!
ブラウザを2つ開いて、送信を押してみてください。
片方で送信すると片方のブラウザにリアルタイムで表示されると思います。
とても簡単にできますのでぜひ活用してみてください。
ニシザワです。
本日はLaravel EchoとPusherを使ってリアルタイムチャットが簡単にできたのでその方法を書きます。
Pusherの登録
Pusherは簡単に双方向通信ができるAPIサーバーのサービスです。まずは、こちらの登録をします。
次にCreate new appよりアプリを作成してください。
③は今回はなんでもいいですが、Vanilla Jsを選択
④はLaravelを選択
⑤は適当にコメントを入れていただいてCreate my appで作成してください。
Eventの作成
app/Events/以下にposted.phpを作成しEventを作成します。
<?php
namespace App\Events;
use App\Models\Post;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class Posted implements ShouldBroadcast
{
use SerializesModels;
/**
* @var Post
*/
public $post;
/**
* Posted constructor.
* @param Post $post
*/
public function __construct(Post $post)
{
$this->post = $post;
}
/**
* @return Channel|Channel[]
*/
public function broadcastOn()
{
return new Channel('post');
}
}
new Channelのところはrouteで定義するchannel名を入れます。今回は認証は入れませんが、入れたい場合はPrivateChannelを使います。
Routeの定義
route/channels.phpに以下を追加
<?php
Broadcast::channel('post', function (){
return true;
});
コールバックのところは認証を入れる場合はここで制限します。今回は認証など条件は必要ないので常にtrueを返しています。
投稿に必要なCreateとIndexを作成
表示と投稿用を実装します。migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->text("text");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Route
route/web.php
<?php
Route::get("posts", 'PostController@index')->name('post.index');
Route::post("posts/create", 'PostController@create')->name('post.create');
Model
app/Models/Post.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class Post
* @package App\Models
*
* @property string $text
*/
class Post extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'text'
];
}
Controller
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Events\Posted;
use App\Models\Post;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PostController extends Controller
{
/**
* @return View
*/
public function index() : View
{
$posts = Post::all();
return view('channels.index',[
"posts" => $posts
]);
}
/**
* @param Request $request
* @return JsonResponse
*/
public function create(Request $request) : JsonResponse
{
$post = new Post($request->all());
$post->save();
event(new Posted($post));
return response()->json(['message' => '投稿しました。']);
}
}
View
resources/views/channels/index.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<ul id="board">
@foreach($posts as $post)
<li>{{ $post->text }}</li>
@endforeach
</ul>
</div>
<div class="card-body">
<input type="text" id="text">
<input type="submit" value="送信" id="submit">
</div>
</div>
</div>
</div>
</div>
@endsection
LaravelのAuthで作られるテンプレートを代用してます。
Pusherの設定
composer require pusher/pusher-php-server "~3.0"
composerで必要なパッケージをインストールします。
npm install --save laravel-echo pusher-js
Laravel EchoとpusherJsもインストールします。.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your id
PUSHER_APP_KEY=your key
PUSHER_APP_SECRET=your secret
PUSHER_APP_CLUSTER=your claster
次に環境変数の設定です。pusherのダッシュボード>App Keysにあるのでそちらから写します。
config/app.phpで
//App\Providers\BroadcastServiceProvider::class,
コメントアウトされているBroadcast用のProviderを外します。
Laravel Echoでリスナーを作成
resources/assets/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,
encrypted: true
});
上記のコードを追加します。resources/assets/js/app.js
$(document).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$("#submit").click(function () {
const url = "/posts/create";
$.ajax({
url: url,
data: {
text: $("#text").val()
},
method: "POST"
});
return false;
});
window.Echo.channel('post')
.listen('Posted', (e) => {
$("#board").append('<li>' + e.post.text + '</li>');
});
});
app.jsの最後に投稿したときの投稿処理とpusherから受けとるリスナー処理を書きます。channel('post')のpostはrouteで定義したchannel名になります。
listen('Posted'のPostedはEventで定義したクラス名が入ります。
名前空間などが違う場合はEventで定義したクラスに別名をつけることも可能です。
ざっと説明しましたが、これで完了です!
ブラウザを2つ開いて、送信を押してみてください。
片方で送信すると片方のブラウザにリアルタイムで表示されると思います。
とても簡単にできますのでぜひ活用してみてください。