I’ve been trying to implement a chat application that can listen to a NewMessage event in my backend which is in Laravel and I want to read these events in my Frontend which is a vite-react-app.
I have a soketi docker image running in my localhost with this command:
docker run -p 6001:6001 -p 9601:9601 quay.io/soketi/soketi:1.4-16-debian
Chat application is using pusher-php-server, soketi , Laravel (backend), ReactJs (frontend) with Pusher-js and Laravel-Echo.
Backend :
- The route for triggering a test event in the backend =
Route::post('testMessage', [ChatController::class, 'testMessage']);
- The ChatController class =
<?php
namespace AppHttpControllers;
use AppEventsNewMessage;
use IlluminateHttpRequest;
class ChatController extends Controller
{
public function testMessage()
{
logger('chatController => testMessage triggered');
$message = 'this is a test message';
broadcast(new NewMessage($message));
return response()->json(['message' => 'Test message sent successfully']);
}
}
- An NewMessage Event =
<?php
namespace AppEvents;
use AppModelsChat;
use IlluminateBroadcastingChannel;
use IlluminateBroadcastingInteractsWithSockets;
use IlluminateBroadcastingPresenceChannel;
use IlluminateBroadcastingPrivateChannel;
use IlluminateContractsBroadcastingShouldBroadcast;
use IlluminateFoundationEventsDispatchable;
use IlluminateQueueSerializesModels;
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public string $message;
public function __construct(string $message)
{
$this->message = $message;
logger('NewMessage Event Triggered. Message = ' . $this->message);
}
public function broadcastOn(): array
{
return [
new Channel('public'),
new PrivateChannel('private')
];
}
public function broadcastAs()
{
return 'new.message';
}
}
- Broadcasting.php file =
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'host' => env('PUSHER_HOST') ?: 'api-' . env('PUSHER_APP_CLUSTER', 'mt1') . '.pusher.com',
'port' => env('PUSHER_PORT', 443),
'scheme' => env('PUSHER_SCHEME', 'https'),
'encrypted' => true,
'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
- .env file (pusher config) =
# pusher config
PUSHER_APP_ID=app-id
PUSHER_APP_KEY=app-key
PUSHER_APP_SECRET=app-secret
PUSHER_HOST=1270.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
BROADCAST_DRIVER=pusher
- channels.php =
// public chat channel
Broadcast::channel('public', function () {
return true;
});
Frontend:
- Here I’m trying to listen to the NewMessasge Event on a demo CRA on the same local system with this code:
// Laravel-echo
var echo = new Echo({
broadcaster: "pusher",
cluster: "mt1",
key: "app-key",
wsHost: "127.0.0.1",
wsPort: 6001,
wssPort: 6001,
forceTLS: false,
encrypted: true,
disableStats: true,
enabledTransports: ["ws", "wss"],
});
// pusher
var client = new PusherJs("app-key", {
wsHost: "127.0.0.1",
wsPort: 6001,
cluster: "mt1",
forceTLS: false,
encrypted: false,
enableStats: true,
enabledTransports: ["ws", "wss"],
});
useEffect(() => {
let count = 1;
const channel = echo.channel("public");
console.log('Laravel-echo subscribed = ', channel);
channel.listen("new.message", (e) => {
console.log("New Message Event Occurred ....");
console.log(e);
setMessageEventCount(count);
count++;
});
}, []);
useEffect(() => {
let count = 1;
const channel = client.subscribe('public');
console.log('Pusher subscribed = ', channel);
channel.bind('new.message', (e) => {
console.log('New Message Event Occurred ....');
console.log(e);
setMessageEventCount(count);
count++;
})
}, []);
I’ve tried listening to the event using both Laravel-echo and Pusher-js. But no luck.
The frontend is connecting to the ‘public’ channel in both the cases (echo and pusher). But the events are not getting triggered/listened to my frontend.
2
Answers
The Redis Queue was not running because of which the events were not getting triggered or listened. I used this command to run queue:
php artisan queue:work --queue=high,default
Anyone stumbling accros this issue and not being able to solve it with this… This might be another solution you (or at least I) didn’t think of:
If you use Soketi in combination with Laravel Echo (and in my case in VueJS), make sure the default Soketi vars are set correctly, in my case for example:
Make sure these vars are the same as the vars in PUSHER_*