i have been trying to solve this problem since long time but i found nothing, i am trying to build a simple private chat app using
- Laravel
- Socketio
- Redis,
i built the chat but i have a bug that i can't fix yet, the problem is when i first open the chat or on page reload when i send the first message it shows up to the receiver at the right time but it doesn't show to its owner although it's emitted to both users , then every other message shows up to both users at the right time , and here is the code, also the errorevent does the same, it's supposed to send the error message to the its owner but it does not send the first message through socketio .
server.js
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
var rediserror = new Redis();
redis.psubscribe('private-message-channel.*' , function(err , count) {
console.log('error is '+err+' and count is '+count);
});
redis.on('pmessage' , function(pattern ,channel , message) {
console.log('channel is '+channel+' and message is '+message);
message = JSON.parse(message);
io.emit(channel+':'+message.event , message.data);
});
rediserror.psubscribe('private-error-channel.*' , function(err , count) {
console.log('error is '+err+' and count is '+count);
});
rediserror.on('pmessage' , function( pattern ,channel , message) {
console.log("channel is " + channel + " and message is: " + message);
message = JSON.parse(message);
io.emit(channel+':'+message.event , message.data);
});
var redischatchannel = new Redis();
redischatchannel.psubscribe('private-chat-channel.*' , function(err , count){
console.log('error is '+err+' and count is '+count);
});
redischatchannel.on('pmessage' , function(pattern , channel , message) {
console.log("channel is "+channel +" and message is: "+message);
message = JSON.parse(message);
io.emit(channel+':'+message.event , message.data);
});
http.listen(3000, function () {
console.log('server lisening at port 3000');
});
chatroom.blade.php
@extends('layouts.app')
@section('content')
@if(!$messages)
<h3>No Messages in your chat with yet</h3>
@else
<div id="msgs">
@foreach($messages as $message)
<p><em><b></b></em> : </p>
<hr>
@endforeach
</div>
@endif
<form id="chatform" >
<div class="form-group">
<input type="text" id="body"/>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Send" />
</div>
</form>
@endsection
@section('script')
<script>
var socket = io('http://localhost:3000');
socket.removeAllListeners(`private-chat-channel..:App\\Events\\ChatEvent`);
socket.on(`private-chat-channel..:App\\Events\\ChatEvent` , function(msg){
//console.log(msg);
$('#msgs').append(`<p><em><b>${msg.data.fromusername}</b></em> : ${msg.data.body}</p><hr>`)
});
$('#chatform').submit(function(e) {
e.preventDefault();
var body = $('#body').val();
var chatid = ;
axios.post('/store-message' , {
body:body,
chatid:chatid
}).then( function(response){
console.log(response);
var message=response;
socket.removeAllListeners(`private-message-channel.${message.data.from}.${message.data.to}:App\\Events\\MessageEvent`);
socket.on(`private-message-channel.${message.data.from}.${message.data.to}:App\\Events\\MessageEvent` , function(msg) {
console.log(msg);
$('#msgs').append(`<p><em><b>${msg.data.fromusername}</b></em> : ${msg.data.body}</p><hr>`);
$('#body').val('');
});
}).catch(function(error){
socket.removeAllListeners(`private-error-channel.:App\\Events\\ErrorMessage`);
socket.on(`private-error-channel.:App\\Events\\ErrorMessage` , function(msg){
console.log(msg);
});
console.error(error);
});
})
</script>
@endsection
store_message method from chat controller
public function store_message(Request $request)
{
$validator = Validator::make($request->all() , [
'chatid' => 'required',
'body' => 'required'
]);
if($validator->fails())
{
event(new ErrorMessage( auth()->user() ,$validator->errors()));
return response()->json(['errors' => $validator->errors()] , 400);
}
//dd($request);
if(!Chat::find($request->input('chatid')))
{
event(new ErrorMessage( auth()->user() ,'chat not found'));
return response()->json(['error'=>'error chat not found'] , 400);
}
$chat = Chat::find($request->chatid);
if($chat['user1_id'] == auth()->user()->id)
{
$to = $chat['user2_id'];
} elseif($chat['user2_id'] == auth()->user()->id)
{
$to = $chat['user1_id'];
}
//dd($to);
$message = new Message;
$message->chat_id = $request->chatid;
$message->from = auth()->user()->id;
$message->to = $to;
$message->fromusername= auth()->user()->name;
$message->tousername = User::find($to)->name;
$message->body = $request->body;
$message->save();
event(new MessageEvent(auth()->user() , $message));
event(new ChatEvent($request->chatid , $to ,$message));
return $message;
}
MessageEvent.php
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
class MessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $data;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user , $data )
{
$this->data = $data;
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('message-channel.'.$this->user->id.'.'.$this->data->to);
}
}
ErrorEvent.php
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
class ErrorMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $data;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user , $data)
{
$this->user = $user;
$this->data = $data;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('error-channel.'.$this->user->id);
}
}
via Chebli Mohamed
Aucun commentaire:
Enregistrer un commentaire