Needed some time to get back to this problem, but now I found a answer with minimum overwriting of vendor code.
The files of interest are below the Channels folder:
|-- laravel-websockets
| |-- src
| | |-- WebSockets
| | | |-- Channels
| | | | |-- ChannelManagers
| | | | |-- ArrayChannelManager.php
| | | |-- Channel.php
| | | |-- ChannelManager.php
| | | |-- PresenceChannel.php
| | | |-- PrivateChannel.php
In the Channel.php
, PresenceChannel.php
and PrivateChannel.php
all pusher server relevant events are handled. Like, subscribing and sending messages. The class ArrayChannelManager
controls what class is used for PrivateChannel, PresenceChannel, and Channel.
Laravel-websockets gives you the possibility to use your own channel manager for your project, specified in /config/websockets.php -> 'channel_manager'
.
To add Laravel events to pusher server events I overloaded ArrayChannelManager
and PrivateChannel
(you can overload the others Channels too if needed) and added Laravels queued events. In /config/websockets.php
I used my overloaded class as channel_manager.
/config/websockets.php:
'channel_manager' => \App\Lib\Overwrite\LaravelWebsockets\ArrayChannelManager::class,
My overloaded ArrayChannelManager:
<?php
namespace App\Lib\Overwrite\LaravelWebsockets;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\Channel;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager as ArrayChannelManagerBase;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
use App\Lib\Overwrite\LaravelWebsockets\PrivateChannel;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
class ArrayChannelManager extends ArrayChannelManagerBase
{
protected function determineChannelClass(string $channelName): string
{
if (Str::startsWith($channelName, 'private-')) {
return PrivateChannel::class;
}
if (Str::startsWith($channelName, 'presence-')) {
return PresenceChannel::class;
}
return Channel::class;
}
};
In my overloaded PrivateChannel
file I hook a MyPusherLaravelEvent
to the pusher subscribe event:
<?php
namespace App\Lib\Overwrite\LaravelWebsockets;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PrivateChannel as PrivateChannelBase;
use Ratchet\ConnectionInterface;
use stdClass;
class PrivateChannel extends PrivateChannelBase
{
public function subscribe(ConnectionInterface $connection, stdClass $payload)
{
parent::subscribe($connection, $payload);
\App\Events\MyPusherLaravelEvent::dispatch($this->channelName);
}
}
Its important to use Laravels queued events to separate the event handling from the pusher server. https://laravel.com/docs/8.x/events#queued-event-listeners
You can also hook your events to the Channel::broadcast...
functions and then parse the content to react on certain client commands with your server.
Overload the functions in a generic way, so the vendor code can be updated without you breaking it with your overloads.