Your current implementation for broadcasting messages in a private chat using Laravel, Pusher, and VueJS looks solid. However, to address your requirement of updating the sidebar with the last message, you can extend your current approach slightly.
Solution
-
Modify the
MessageSentEvent:- Add a new property to hold the conversation details.
- Update the constructor to accept and set this new property.
-
Update the VueJS Component:
- Listen for the
MessageSentevent. - Update the sidebar with the new message details.
- Listen for the
Updated MessageSent Event
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public ConversationsMessages $message;
public $conversation;
public function __construct(ConversationsMessages $message, $conversation)
{
$this->message = $message;
$this->conversation = $conversation;
}
public function broadcastOn(): Channel
{
return new Channel('private_chat.' . $this->message->conversation_id);
}
public function broadcastAs(): string
{
return 'MessageSent';
}
public function broadcastWith(): array
{
return [
'message' => $this->message,
'conversation' => $this->conversation,
];
}
}
Update the Broadcast Channel
Ensure that the user is authorized to listen to the channel:
Broadcast::channel('private_chat.{conversationId}', function ($user, $conversationId) {
$conversation = Conversations::with('participants')->find($conversationId);
if (!$conversation) return false;
return $conversation->participants->contains($user->id);
});
VueJS Component
In your VueJS component, listen for the MessageSent event and update the sidebar accordingly.
Echo.channel('private_chat.' + conversationId)
.listen('.MessageSent', (e) => {
// Update the chat window with the new message
this.messages.push(e.message);
// Update the sidebar with the last message details
let conversation = this.conversations.find(c => c.id === e.conversation.id);
if (conversation) {
conversation.last_message = e.message.content;
conversation.last_message_date = e.message.created_at;
}
});
Controller Update
When you dispatch the MessageSent event, ensure you pass the conversation details:
public function sendMessage(Request $request)
{
$message = new ConversationsMessages();
$message->conversation_id = $request->conversation_id;
$message->user_id = auth()->id();
$message->content = $request->content;
$message->save();
$conversation = Conversations::with('participants')->find($request->conversation_id);
broadcast(new MessageSent($message, $conversation))->toOthers();
return response()->json(['status' => 'Message Sent!']);
}
Summary
By extending the MessageSent event to include conversation details and updating your VueJS component to handle these details, you can efficiently update the sidebar with the last message information. This approach keeps your code clean and maintains the separation of concerns.