`Problem Description:
I'm working on a chat application using Vue 3, Axios, and Laravel Echo (with Pusher) for real-time updates. I'm encountering an issue where I receive the following error:
``ChatArtisanClient.vue:68 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'discussion_id')
at ChatArtisanClient.vue:68:52
at renderList (chunk-U6BEPC57.js?v=670d87f9:4352:16)
at ChatArtisanClient.vue:1:1
In my onMounted
lifecycle hook, I fetch initial messages and set up a listener for real-time updates as follows:`
`class MessageNotification implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public $user;
public $taskId;
public $userId;
public function __construct($message, $user, $taskId, $userId)
{
$this->message = $message;
$this->user = $user;
$this->taskId = $taskId;
$this->userId = $userId;
}
public function broadcastOn()
{
return new PrivateChannel('task.' . $this->taskId . 'user.' . $this->userId);
}
}`
`Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
use Illuminate\Support\Facades\Log;
Broadcast::channel('task.{taskId}.user.{userId}', function ($user, $taskId, $userId) {
Log::info('Tentative de connexion au canal privé', ['user_id' => $user->id, 'task_id' => $taskId, 'userId' => $userId]);
$discussion = Discussion::where('task_id', $taskId)
->where('artisan_user_id', $user->id)
->first();
if (!$discussion) {
Log::warning('Aucune discussion trouvée', ['user_id' => $user->id, 'task_id' => $taskId]);
return false;
}
Log::info('Discussion trouvée', ['discussion_id' => $discussion->id, 'task_id' => $taskId, 'artisan_user_id' => $discussion->artisan_user_id, 'client_user_id' => $discussion->user_id]);
$isParticipant = $discussion->user_id === $userId || $discussion->artisan_user_id === $user->id;
Log::info('Vérification des participants', ['is_participant' => $isParticipant]);
return $isParticipant;
});
`
`use App\Events\MessageNotification;
use App\Notifications\NewMessageNotification;
class ChatsController extends Controller
{
public function index()
{
$messages = Message::with('user')->get();
return Inertia::render('Chat', compact('messages'));
}
public function fetchMessages()
{
return Message::with('user')->get();
}
public function store(Request $request)
{
// Récupérer l'utilisateur authentifié (ici l'artisan)
$artisan = Auth::user();
$taskId = $request->taskId;
// Récupérer l'utilisateur (le client) associé à la tâche
$task = Task::find($taskId);
$userId = $task->user_id; // Identifiant du client
// Vérifier si une discussion existe déjà entre l'artisan et le client pour la tâche
$discussion = Discussion::where('task_id', $taskId)
->where('artisan_user_id', $artisan->id)
->first();
// Si aucune discussion n'existe, en créer une nouvelle
if (!$discussion) {
$discussion = Discussion::create([
'task_id' => $taskId,
'user_id' => $userId, // Identifiant du client
'artisan_user_id' => $artisan->id // Identifiant de l'artisan
]);
}
// Créer un nouveau message dans la discussion
$message = $discussion->messages()->create([
'user_id' => $artisan->id, // Identifiant de l'utilisateur envoyant le message (l'artisan ici)
'message' => $request->message,
]);
// Diffuser l'événement sur le canal privé basé sur les IDs des utilisateurs
broadcast(new MessageNotification($message, Auth::user(), $taskId, $artisan->id))->toOthers();
return ['status' => 'Message envoyé'];
}
}`
`const props = defineProps({
taskId: Number,
userId: Number
});
const msg = ref([]);
const form = useForm({
message: "",
taskId: props.taskId,
});
onMounted(async () => {
try {
const response = await axios.get('/messages');
msg.value = response.data;
console.log("MessageNotification");
// Placez ici le reste du code qui dépend de msg.value
console.log(msg.value);
} catch (error) {
console.error('Erreur lors de la récupération des messages:', error);
}
});
window.Echo.private(`task.${props.taskId}.user.${props.userId}`).listen('MessageNotification', (response) => {
console.log("MessageNotification");
console.log(response);
msg.value.push({
message: response.message.message,
user: response.user
});
//alert('Show without refresh!');
});
const submit = () => {
axios.post("/chat", form).then((response) => {
msg.value.push(response.data.message);
form.message = null;
});
};
</script>
<template>
<AppLayout title="Tâche">
<Head title="Chat" />
<template>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">Chat</h2>
</template>
<div class="py-12">`your text`
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="font-bold text-xl mb-4 p-3">Messages</div>
<hr/>
<div class="overflow-y-auto max-h">
<ul class="chat list-none p-6">
<li v-for="(message, i) in msg" :key="i" class="left clearfix">
<div class="clearfix">
<div class="header">
<strong class="text-blue-500">
{{ message.discussion_id }} :
</strong>
{{ message.message }}
</div>
</div>
</li>
</ul>
</div>
<hr>
<div class="mt-4 p-4">
<div class="flex items-center">
<input
id="btn-input"
type="text"
name="message"
class="border border-gray-200 rounded w-full"
v-model="form.message"
@keyup.enter="submit"
placeholder="Type your message here..."
/>
<span class="ml-2">
<button class="bg-blue-500 text-white px-4 py-2 rounded" id="btn-chat" @click="submit">
Send
</button>
</span>
</div>
</div>
</div>
</div>
</div>
</AppLayout>
</template>`
The message already in the database are displays without any errors.
I tried to change the information retrieved and also checked the models; I expect everything is okay. I tried to display log messages, but the window.Echo part doesn't show anything.`
After doing some research, I figured out that my route wasn't displaying the error message correctly, so I added a try-catch block. I found out that my controller was showing some errors related to the fact that the parameters of the route were not being sent correctly, so I used the append method instead of sending the form, and it worked.
const submit = async (e) => {
e.preventDefault();
var formData = new FormData();
formData.append("message", form.message);
formData.append("taskId", props.taskId);
try {
axios.post("/chat", formData).then((response) => {
msg.value = response.data;
form.message = null
});
} catch (error) {
console.error('Erreur lors de l\'envoi du message:', error);
}
};