I'm struggling with implementing Websocket on Laravel.
I'm using laravel-echo-server
on the server side. I have some notifications that I want to send with Websocket and then get on the client-side with Laravel echo.
I'll write down what I've done:
- I've downloaded socket.io-client.js v2.3.1 and added
<script src="{{ asset('path/socket.io.js') }}"></script>
before<script src="{{ asset('path/app.js') }}"></script>
in my blade file. - Configured Redis as queue connection and broadcast driver
- Installed laravel-echo-server with
npm install -g laravel-echo-server
- Configured laravel-echo-server with
laravel-echo-server init
command. Configuration is:
{
"authHost": "http://127.0.0.1:8000",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "9d98443b1518e747",
"key": "7bd6ea5e93100621942c1a21093e4621"
}
],
"database": "redis",
"databaseConfig": {
"redis": {},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "6006",
"protocol": "http",
"socketio": {},
"secureOptions": 67108864,
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "http://127.0.0.1:8000",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
- Installed laravel echo with
npm install --save laravel-echo
- In bootstrap.js configured Echo like this:
import Echo from 'laravel-echo';
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.Laravel.wsurl + ':6006',
disableStats: true,
enabledTransports: ['ws', 'wss'],
transports: ['websocket', 'polling', 'flashsocket'],
auth: {
headers: {
'Authorization': 'Bearer ' + window.Laravel.wskey,
'X-CSRF-TOKEN': window.Laravel.csrfToken
}
}
});
- I've run
npm run dev
to compile the code. - This is my notification class:
<?php
namespace Modules\Ticket\Notifications;
use App\Channels\SmsChannel;
use App\Channels\UserDatabaseChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\BroadcastMessage;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\SerializesModels;
use Modules\Ticket\Entities\Ticket;
use Modules\Ticket\Jobs\AdminTicketCreatedSms;
class AdminTicketCreated extends Notification implements ShouldBroadcast, ShouldQueue
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public Ticket $ticket;
private int $userId;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(Ticket $ticket)
{
$this->userId = $ticket->user_id;
$this->ticket = $ticket;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable): array
{
// return [SmsChannel::class, 'mail', 'broadcast', UserDatabaseChannel::class];
return ['broadcast', UserDatabaseChannel::class];
}
public function toMail($notifiable)
{
return (new MailMessage())
->subject('ارسال تیکت توسط ارزی لند')
->replyTo($notifiable->email, $notifiable->name)
->view('emails.ticket_send_admin', ['user' => $notifiable, 'ticket' => $this->ticket]);
}
public function toSms($notifiable)
{
dispatch(new AdminTicketCreatedSms($notifiable->user, $this->ticket))->delay(60);
}
public function toDatabase($notifiable)
{
return [
'title' => "تیکت جدید ثبت شد",
'url' => route('notification.show', ['id' => $this->id]),
];
}
public function toBroadcast()
{
return new BroadcastMessage([
'title' => "تیکت جدید ثبت شد",
]);
}
public function broadcastOn()
{
return new PrivateChannel('App.User.' . $this->userId);
}
}
As you see, I'm broadcasting the notification on 'App.User.userId' so in blade I have to be enabled to get it with something like this:
Echo.private('App.User.{{ auth()->id() }}').notification((response) => {
console.log(response);
});
I have three terminals open with these commands:
php artisan serve
php artisan queue:listen --tries=1
laravel-echo-server start
Now, I have a problem:
On the client-side laravel echo doesn't subscribe to the event! (I'm using a test route to trigger the notification and it's working in queue and laravel-echo-server console)
BTW, I'm using Windows 10 and Wampserver for development.
In addition, I've also enabled BroadcastServiceProvider
and added this in channels.php:
Broadcast::channel('App.User.{id}', function ($user, $id) {
return true; // this is for test, I have logic for this part
});
I'll be appreciated any help. :)