gpt4 book ai didi

laravel - 使用 Laravel-Websockets 向特定用户发送消息(一对一聊天)

转载 作者:行者123 更新时间:2023-12-04 16:13:09 24 4
gpt4 key购买 nike

我的应用程序中有一个 websocket 群聊,可以将用户的消息广播给所有其他用户。我也想进行一对一的聊天,只向双方广播消息。我如何告诉 websocket 将消息广播给特定用户?

我的 Controller :

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Message;

use App\Events\MessageSent;

use Auth;

class ChatsController extends Controller
{

public function index()
{
if (Auth::check() === false) {

return view('login');

}
else
{

return view('chats');

}
}

public function fetchMessages()
{
return Message::with('user')->get();
}

public function sendMessage(Request $request)
{
$message = auth()->user()->messages()->create([
'message' => $request->message
]);
broadcast(new MessageSent($message->load('user')))->toOthers();
return ['status' => 'success'];
}
}

我的 Vue 文件:

<template>
<div class="row">

<div class="col-8">
<div class="card card-default">
<div class="card-header">Messages</div>
<div class="card-body p-0">
<ul class="list-unstyled" style="height:300px; overflow-y:scroll" v-chat-scroll>
<li class="p-2" v-for="(message, index) in messages" :key="index" >

<div style="background: #009afb; padding: 8px; color: white; border-radius: 15px;">

<img v-if="message.user.image == 'img'" src="https://www.stickpng.com/assets/images/585e4bf3cb11b227491c339a.png" style="width: 35px; height: 35px;">
<img v-else v-bind:src="'../images/' + message.user.image"
style="width: 35px; height: 35px;border-radius: 50%;">

<strong>{{ message.user.name }} {{ message.user.surname }} :</strong>

{{ message.message }}

<p style="color:lightgray;">
{{ message.created_at }}
</p>

</div>

</li>
</ul>
</div>

<input
@keydown="sendTypingEvent"
@keyup.enter="sendMessage"
v-model="newMessage"
type="text"
name="message"
placeholder="Enter your message..."
class="form-control">
</div>
<span class="text-muted" v-if="activeUser" >{{ activeUser.name }} is typing...</span>
</div>

<div class="col-4">
<div class="card card-default">
<div class="card-header">Active Users</div>
<div class="card-body">
<ul>
<li class="py-2" v-for="(user, index) in users" :key="index">
{{ user.name }}
</li>
</ul>
</div>
</div>
</div>

</div>
</template>
<script>
export default {
props:['user'],
data() {
return {
messages: [],
newMessage: '',
users:[],
activeUser: false,
typingTimer: false,
}
},
created() {
this.fetchMessages();
Echo.join('chat')
.here(user => {
this.users = user;
})
.joining(user => {
this.users.push(user);
})
.leaving(user => {
this.users = this.users.filter(u => u.id != user.id);
})
.listen('MessageSent',(event) => {
this.messages.push(event.message);
})
.listenForWhisper('typing', user => {
this.activeUser = user;
if(this.typingTimer) {
clearTimeout(this.typingTimer);
}
this.typingTimer = setTimeout(() => {
this.activeUser = false;
}, 3000);
})
},
methods: {
fetchMessages() {
axios.get('messages').then(response => {
this.messages = response.data;
})
},
sendMessage() {
this.messages.push({
user: this.user,
message: this.newMessage
});
axios.post('messages', {message: this.newMessage});
this.newMessage = '';
},
sendTypingEvent() {
Echo.join('chat')
.whisper('typing', this.user);
}
}
}
</script>

我的表有id、user_id和message字段。

最佳答案

你好,我也遇到了同样的问题,已经解决了但是请注意,我有额外的逻辑

1-在channels.php

Broadcast::channel('chat.{ticketId}', function ($user, $ticketId) {
$ticket = \App\Models\Ticket::find($ticketId);
return $user->id == $ticket->asked_user_id || $user->id == $ticket->responded_user_id;
});

2- 我只允许用户互相聊天,询问其中一个人的支持票或回复用户的管理员

在我的事件中我有这段代码

class MessageSentEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;


public $message;
public $ticket;

/**
* Create a new event instance.
*
* @return void
*/
public function __construct(TicketMEssage $message, Ticket $ticket)
{
$this->message = $message;
$this->ticket = $ticket;
}

/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PresenceChannel('chat.' . $this->ticket->id);
}

public function toBroadcast()
{
return new MessageSentEvent($this->message);
}

}

3- 我收到这样的消息和票

$ticket = Ticket::find($id);
$messages = $ticket->messages;
$messages->load('user');

return response()->json([
'messages' => $messages,
'ticket' => $ticket,
'user' => auth()->user()
]);

4- 我像下面这样存储和广播消息

$ticket = Ticket::find($request->ticket_id);
$message = $ticket->messages()->create([
'message' => $request->message,
'for' => auth()->id() == $ticket->asked_user_id ? TicketMessage::FOR_USER['asked'] : TicketMessage::FOR_USER['responded'],
'user_id' => auth()->id(),
]);

$message->load('user');
broadcast(new MessageSentEvent($message, $ticket));
return ['status' => 'success', 'message' => $message];

5-和js文件中的重要部分(React或Vue或...)

 window.Echo.join(`chat.${props.ticketId}`)
.listen('MessageSentEvent', (message) => {
setMessages((prevState) => [...prevState, message.message]);
});

我只收听带有我从 props 获得的票证 ID 的 channel (你应该以任何方式传递它)

关键部分是1和4和5

希望这对你有帮助:)))

关于laravel - 使用 Laravel-Websockets 向特定用户发送消息(一对一聊天),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56964429/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com