pusher.com + laravel mixでPrivate Channelを実装
これをPublicChannelからPrivate Channelにする
App/Events/pusher_sent.php
1, pusher送信のPrivate化は、本当にPrivateをつけるだけ
1 2 3 4 5 6 7 |
// チャンネル名・イベント名を指定 public function broadcastOn() { //return new Channel('my-channel'); // プレフィックス(private-)は自動的に付与されるので不要 return new PrivateChannel('channel'); } |
2, 受信JSは、window.Echo.channelからwindow.Echo.privateに書き換える。
resources/js/app.js
1 2 3 4 5 6 7 8 9 |
$(document).ready(function() { //受信するチャネル名・イベント名を指定&処理を記述 //window.Echo.channel('my-channel') window.Echo.private('channel') // イベント名の前にドットをつけるのを忘れずに!!(app/Eventsがデフォ) .listen('.my-event', (e) => { console.log(e); }); }); |
3, この状態で、pusher受信するとapp.js:38658 POST http://localhost/broadcasting/auth 404 (Not Found)というエラーになる。
a, PrivateChannelは必ずユーザ認証が必要(プライベートだから)
b, そのためにauthEndpoint(デフォルトだとドメイン名/broadcasting/auth)にアクセスしに行って、認証済みか確認する
c, resources/js/bootstrap.jsに、正しいパスでauthEndpointを指定すればOK!(app.jsをコンパイルしなおしてF5リロードが必要)
1 2 3 4 5 6 7 8 9 10 11 12 |
import Echo from 'laravel-echo' window.Pusher = require('pusher-js'); window.Echo = new Echo({ authEndpoint : 'http://localhost/chat/public/broadcasting/auth', broadcaster: 'pusher', key: process.env.MIX_PUSHER_APP_KEY, cluster: process.env.MIX_PUSHER_APP_CLUSTER, encrypted: true, }); |
4, この状態で、pusher受信するとapp.js:38658 POST http://localhost/chat/public/broadcasting/auth 403 (Forbidden)というエラーになる(認証に失敗している)
routes/channels.phpに、認証処理を記述する。
1 2 3 4 5 6 |
// プライベートチャネルには、認証処理が必須! // プレフィックス(private-)は自動的に付与されるので不要 Broadcast::channel('channel', function () { // とりあえず、認証はせずに常にOK return true; }); |
ここまでやって、Public Channelと同じ事を、Private Channelでも出来るようになった!
このままだと意味があまり無いので、ユーザー認証をからめた処理を行う(現状だと、channel名とevent名が分かっていれば、誰でも内容が見えてしまう)
routes/web.php
1 2 3 4 |
Route::get('/sent/{user_id}', function($user_id){ // インスタンス生成するだけで、自動的にpusher送信してくれる event(new App\Events\pusher_sent($user_id, 'user_idが'.$user_id.'の人へ')); }); |
App\Events\pusher_sent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// implements ShouldBroadcastしないとpusher送信してくれない class pusher_sent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; // インスタンス生成する時に、ユーザIDとテキストを受け取り、pusher.comへ送信 public $user_id; public $message; public function __construct($user_id, $message) { $this->user_id = $user_id; $this->message = $message; } // チャンネル名・イベント名を指定 public function broadcastOn() { //return new Channel('my-channel'); // プレフィックス(private-)は自動的に付与されるので不要 // pusherへ送信されるチャネル名は"private-channel.1"となる return new PrivateChannel('channel.' . $this->user_id ); } public function broadcastAs() { return 'my-event'; } } |
http://localhost/chat/public/sent/1 で、pusher.comへ送信出来たか確認する。
特定のユーザのみ受信できるようにするためには
1, resources/view/layout/app.blade.php(共通ヘッダフィアル)で、jsでもログインIDが使えるようにする
1 2 3 4 5 |
<script> window.Laravel = {!! json_encode([ 'user' => auth()->check() ? auth()->user()->id : null, ]) !!}; </script> |
2, app.js(laravel mixでコンパイルされた統合ファイル)で、チャネル名にログインユーザIDを指定する。
1 2 3 4 5 6 7 8 9 10 |
$(document).ready(function() { //受信するチャネル名・イベント名を指定&処理を記述 //window.Echo.channel('my-channel') //自分のログインIDでpusherから受信する! window.Echo.private('channel.' + window.Laravel.user) // イベント名の前にドットをつけるのを忘れずに!!(app/Eventsがデフォ) .listen('.my-event', (e) => { console.log(e); }); }); |
3, routes/channels.phpで、ユーザIDが一致しているか判定する
Broadcast::channelのクロージャ第一引数は、ログインしたユーザ情報が自動的に格納されるので認証に使える!
こうする事によって、チャネル名を”private-channel.2″としても、ユーザID=2のユーザ以外は受信できなくなる。
1 2 3 4 5 6 |
// プライベートチャネルには、認証処理が必須!プレフィックス(private-)は自動的に付与されるので不要 // 第一引数は認証済みユーザ情報が自動的に格納される Broadcast::channel('channel.{id}', function ($user,$id) { // ログインしているユーザIDとチャネル名の宛先となっているユーザIDが一致していたらTRUE return (int) $user->id === (int) $id; }); |