config/app.php
L BroadcastServiceProviderのコメントアウトを外します。
App\Providers\BroadcastServiceProvider::class,
クライアント側で必要なパッケージをインストール
$ npm install –save laravel-echo pusher-js
resources/js/bootstrap.js
L コメントアウトを外します
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 });
.env
BROADCAST_DRIVER=pusher // 省略 PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1
$ php artisan make:model Message -m
migrationfile
L rollbackしてもう一度作り直します。
public function up() { Schema::create('messages', function (Blueprint $table) { $table->bigIncrements('id'); $table->integer('user_id'); $table->text('message'); $table->timestamps(); }); }
Model
Message.php
protected $fillable = [ 'user_id', 'message', ]; public function user(){ return $this->belongsTo('App\Models\User'); }
User.php
public function messages(){ return $this->hasMany('App\Models\Message'); }
php artisan make:controller ChatsController
route
Route::get('/post', [ChatsController::class, 'index']); Route::get('/messages', [ChatsController::class, 'fetchMessages']); Route::post('/messages', [ChatsController::class, 'sendMessage']);
ChatsController.php
use App\Models\Message; use Illuminate\Support\Facades\Auth; use App\Events\MessageSent; class ChatsController extends Controller { // public function __construct(){ $this->middleware('auth'); } public function index(){ return view('chat.post'); } public function fetchMessages(){ return Message::with('user')->get(); } public function sendMessage(Request $request){ $user = Auth::user(); $message = $user->messages()->create([ 'message' => $request->input('message') ]); event(new MessageSent($user, $message)); return ['status' => 'Message Sent!']; } }
$ php artisan make:event MessageSent
MessageSent.php
use App\Models\User; use App\Models\Message; class MessageSent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $user, public $message; /** * Create a new event instance. * * @return void */ public function __construct(User $user, Message $message) { // $this->user = $user; $this->message = $message; } /** * Get the channels the event should broadcast on. * * @return \Illuminate\Broadcasting\Channel|array */ public function broadcastOn() { return new PrivateChannel('testApp'); } }
routes/channels.php
L プライベートチャンネルをリッスンする場合は、channels.phpで許可する
Broadcast::channel('testApp', function($user){ return Auth::check(); });
post.blade.php
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link href="{{ mix('css/app.css')}}" rel="stylesheet" type="text/css"> <meta name="csrf-token" content="{{ csrf_token() }}"> </head> <body> <div id="app"> <example-component></example-component> </div> <script src="{{ mix('js/app.js')}}"></script> </body> </html>
$ composer require laravel/ui
$ php artisan ui vue
$ npm install && npm run dev
/resources/js/components/ExampleComponent.vue
<template> <div> <ul> <li v-for="(message, key) in messages" :key="key"> <strong>{{ message.user.name }}</strong> {{ message.message }} </li> </ul> <input v-model="text" /> <button @click="postMessage" :disabled="!textExists">送信</button> </div> </template> <script> export default { data(){ return { text: "", messages: [] }; }, computed: { textExists(){ return this.text.length > 0; } }, created() { this.fetchMessages(); Echo.private("testApp").listen("MessageSent", e=>{ this.messages.push({ message: e.message.message, user: e.user }); }); }, methods: { fetchMessages(){ axios.get("/messages").then(response =>{ this.messages = response.data; }); }, postMessage(message){ axios.post("/messages", {message: this.text}).then(response => { this.text = ""; }); } } } </script>
あれ? 何やこれ。。。componentが上手く表示されんな。。。