'Laravel Echo does not listening
I'm trying to create a simple chat system using socket.io and Laravel Echo. Unfortunately I cannot make this working, Laravel Echo doesn't listen to any events.
First of all I have added two new containers in my docker-compose.yml, one for redis and another for laravel-echo-server:
redis:
image: 'redis:alpine'
ports:
- '6379:6379'
volumes:
- './docker/redis:/data'
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
retries: 3
timeout: 5s
node:
image: node:latest
container_name: socialthess_node
links:
- redis:redis
ports:
- 3000:3000
volumes:
- ./src:/usr/src/app
- /home/data/certs/example.com.crt/:/etc/node/ssl/cert.crt
- /home/data/certs/example.com.key/:/etc/node/ssl/cert.key
command: bash -c "npm install --unsafe-perm -g laravel-echo-server && cd /usr/src/app && laravel-echo-server start"
Configuration for laravel-echo-server.json:
{
"authHost": "https://nginx",
"authEndpoint": "/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {
"port": "6379",
"host": "redis"
}
},
"devMode": false,
"host": "0.0.0.0",
"port": "3000",
"protocol": "https",
"socketio": {},
"sslCertPath": "/etc/node/ssl/cert.crt",
"sslKeyPath": "/etc/node/ssl/cert.key"
}
When I start the app I can see that laravel-echo-server is working fine:
I've included the following within bootstrap.js:
import Echo from "laravel-echo"
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':3000'
})
and the header I've added this line to load the socket package from the container:
<script src="{{ config('app.url') }}:3000/socket.io/socket.io.js"></script>
So when I load the browser console I can see this:
Even the socket call created by the Echo client seems to working fine:
In my application I have enabled the BroadcastServiceProvider::class available within config/app.php.
Then, in the .env file I set redis as BROADCAST_DRIVER.
I've created a channel route to broadcast the available rooms of the chat:
src/routes/channels.php
Broadcast::channel('room.{id}', function ($user, $id) {
return $user->id;
});
Also, I have the following routes within src/routes/web.php:
Route::middleware(['auth'])->group(function () {
Route::get('/chats', [ChatsController::class, 'index'])->name('chats.index');
Route::post('/messages', [MessagesController::class, 'sendMessage'])->name('messages.send');
});
In order to not create confusion, I will only show the sendMessage method of MessagesController:
public function sendMessage(Request $request)
{
$request->validate([
'roomId' => ['required'],
'message' => ['required', 'string', 'max:140'],
]);
$user = $request->user();
$room = Room::findOrFail($request->roomId);
$message = $user->messages()->create([
'room_id' => $room->id,
'message' => $request->message,
]);
broadcast(new MessageSent($user, $room, $message))->toOthers();
return Response::json(['ok' => true]);
}
When an user send a message, the sendMessage is called and the MessageSent event is fired:
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\Boilerplate\User;
use App\Models\Room;
use App\Models\Message;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var \App\Models\User
*/
protected $user;
/**
* @var \App\Models\Room
*/
protected $room;
/**
* @var \App\Models\Message
*/
protected $message;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user, Room $room, Message $message)
{
$this->user = $user;
$this->room = $room;
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PresenceChannel("room.{$this->room->id}");
}
/**
* Broadcast with specific data.
*
* @return array
*/
public function broadcastWith()
{
return array_merge($this->message->toArray(), ['user' => $this->user->only('id', 'name')]);
}
}
The call is maded by pressing the send button:
$('#send-message').on('click', function() {
$.ajax({
type: 'POST',
url: '{{ route('messages.send') }}',
data: {
'roomId': `{{ $room->id }}`,
'message': $('#message').val(),
},
success: function(data) {
console.log(data)
},
error: function(e) {
console.log(e)
}
})
})
Then, whithin the blade file I have this line:
@push('js')
<script>
$(document).ready(function() {
window.Echo.join(`room.{{ $room->id }}`)
.here((users) => {
console.log(users);
})
.joining((user) => {
console.log(user);
})
.leaving((user) => {
console.log(user);
})
.error((error) => {
console.log('echo:error', error);
})
.listen('MessageSent', (e) => {
console.log(e);
})
.listenForWhisper('typing', (user) => {
console.log('typing user => ', user);
})
})
</script>
@endpush
That is supposed to show the messages sent over the room channel, but for some reason I get no response. I also tried to add a . in front of MessageSent but same situation.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|



