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が上手く表示されんな。。。