リアルタイムチャット - message テーブルの message カラムを content カラムへ

(2025-03-04)

リアルタイムチャットには message という言葉がたくさん出てきます。 messages テーブルの message カラムはとても混乱するので、content カラムに変更することにしました。

ファイル編集

app/Http/Controller/ChatsController.php

<?php
namespace App\Http\Controllers;
use App\Events\MessageSent;
use App\Models\Message;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class ChatsController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('chat');
}
public function fetchMessages()
{
return Message::with('user')->get();
}
public function sendMessage(Request $request)
{
$user = Auth::user();
$message = $user->messages()->create([
'content' => $request->content, // 修正: 'message' → 'content'
]);
broadcast(new MessageSent($user, $message))->toOthers();
return ['status' => 'Message Sent!'];
}
}

app/Events/MessageSent.php

<?php
namespace App\Events;
use App\Models\User;
use App\Models\Message;
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 MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public $message;
public function __construct(User $user, Message $message)
{
$this->user = $user;
$this->message = $message;
}
public function broadcastOn()
{
return new PrivateChannel('chat');
}
public function broadcastWith()
{
return [
'user' => $this->user,
'message' => [
'id' => $this->message->id,
'content' => $this->message->content, // 'message' → 'content' に修正
'user_id' => $this->message->user_id,
'created_at' => $this->message->created_at,
],
];
}
}

app/Model/Message.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
use HasFactory;
protected $fillable = ['user_id', 'theme_id', 'content', 'room_id'];
public function theme()
{
return $this->belongsTo(Theme::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function room()
{
return $this->belongsTo(Room::class);
}
}

ChatForm.vue

<script setup>
import { ref } from 'vue';
const props = defineProps({
user: Object
});
const newMessage = ref('');
const emit = defineEmits(['messagesent']);
function sendMessage(e) {
if (newMessage.value === '') return;
emit("messagesent", {
user: props.user,
content: newMessage.value // 修正: 'message' → 'content'
});
newMessage.value = "";
}
</script>
<template>
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="メッセージをタイプしてください..."
v-model="newMessage"
@keydown.enter="sendMessage"
/>
<span class="input-group-btn">
<button class="btn btn-primary" @click="sendMessage">
送信
</button>
</span>
</div>
</template>

ChatMessage.vue

<script setup>
defineProps({
messages: Array,
user: Object
});
</script>
<template>
<ul style="list-style:none">
<li v-for="message in messages"
:key="message.id"
:class="message.user.id === user.id ? 'text-end' : 'text-start'">
<div class="header">
<strong>
<span v-if="message.user.id === user.id">私</span>
<span v-else>{{ message.user.name }}さん</span>
</strong>
</div>
<p>
{{ message.content }} <!-- 修正: 'message' → 'content' -->
</p>
</li>
</ul>
</template>

chat.js

import { createApp, ref } from 'vue';
import ChatMessages from './components/ChatMessages.vue';
import ChatForm from './components/ChatForm.vue';
createApp({
setup () {
const messages = ref([]);
fetchMessages();
window.Echo.private('chat')
.listen('MessageSent', (e) => {
messages.value.push({
content: e.message.content, // 修正: 'message' → 'content'
user: e.user
});
});
function fetchMessages() {
axios.get('/messages').then(response => {
messages.value = response.data.map(msg => ({
content: msg.content, // 修正: 'message' → 'content'
user: msg.user
}));
});
}
function addMessage(message) {
messages.value.push(message);
axios.post('/messages', message).then(response => {
// success
});
}
return {
messages,
fetchMessages,
addMessage
}
}
})
.component('chat-messages', ChatMessages)
.component('chat-form', ChatForm)
.mount('#app');

データベースの変更

messages テーブルの message カラムを content カラムに変更します。