I am using php 7.4, created and set up websocket using Ratchet-PHP. Websocket is working good but the issue here is while injecting my event/notification inside the Websocket Hook function to send message to connected device.
My Socket Command Code:
use RatchetServerIoServer;
use RatchetWebSocketWsServer;
$server = IoServer::factory(
new RatchetHttpHttpServer(
new WsServer(
new ChatFunctionClass()
)
),
6001,
0.0.0.0
);
$this->info("WebSocket server started on $port");
$server->run();
Chat Function Class: Haven’t added all the function just the constructor and connection function hook only.
class ChatServer implements MessageComponentInterface
{
private $clients;
private $redisClient;
public $userConnections;
public function __construct()
{
$this->clients = new SplObjectStorage;
Redis::subscribe(['websocket-notifications'], function (string $message) {
$this->sendMessage(json_decode($message));
});
}
public function onOpen(ConnectionInterface $conn)
{
$querystring = $conn->httpRequest->getUri()->getQuery();
parse_str($querystring, $queryParams);
$userId = $queryParams['user_id'] ?? null;
if ($userId) {
$this->clients->attach($conn, ['user_id' => $userId]);
}
echo "New connection: {$conn->resourceId} for user ID: {$userId}n";
}
Scenerio:
Websocket is running seperataly communicating with browser. Now when something changes through normal HTTP API I want to send notification to specific user/device ie Payment Info Changed/ Address Changed.
What I have tried so far:
i) I connected the websocket within the app and sent message with specific param, on that basis I sent notification to browser (working fine but doesn’t seems to be good approach).
ii) Used Redis Pub/Sub, Subscribing to one channel inside the WebSocket hook function and publish message from API once published it send notification to associated user:
Problem: Redis Sub function blocks the codes.
*Inside Websocket hook class constructor*
Redis::subscribe(['websocket-notifications'], function (string $message) {
$this->sendNotification(json_decode($message));
});
*Publishing from HTTP API*
Redis::publish('websocket-notifications', json_encode([
'name' => 'Test',
'user_id' => '445454',
"message" => "Address Changed by admin"
]));
iii) Tried using ZeroMQ but extension not working/maintained for php >= 7.3
iv) Tried running Redis Sub function/Queue with connection object asynchronously but no luck.
BTW : I haven’t tried Swoole yet.
It works fine in Node.js as it shares the global variable connection/connection list, so same object can be used in API, since PHP runs in separate process and no shareable resource, I don’t know how to overcome this.
So is there any way I can fix this?