我的应用程序中有一个Websocket群组聊天,可将用户的消息广播给所有其他用户。我也想一对一聊天,仅将消息广播到双方。如何告诉网络套接字将消息广播给特定用户?
我的控制器:
<?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字段。
答案 0 :(得分:0)
你好,我也遇到了同样的问题,已经解决了 但请注意,我有额外的逻辑
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 or Vue or ...)
window.Echo.join(`chat.${props.ticketId}`)
.listen('MessageSentEvent', (message) => {
setMessages((prevState) => [...prevState, message.message]);
});
我只听带有我从 props 获得的票证 ID 的频道(你应该以任何方式传递它)
关键部分是1和4和5
希望这对你有帮助:)))