Clarification on Your Questions
1. Is Redis mandatory to communicate from Laravel to WebSocket clients?
Yes, Redis or any other message broker is essential if Laravel and the WebSocket server are running in separate processes. Laravel cannot directly call methods in the Ratchet server; it must use a broker like Redis to pass messages between these isolated components.
2. Is Redis not needed if the frontend sends messages via .send()?
Correct. In this case, the frontend communicates directly with the WebSocket server. Redis is unnecessary because there is no Laravel interaction involved in message delivery.
3. Why does Redis::publish() in Laravel not trigger any response in Ratchet?
The WebSocket server likely uses a blocking subscription (psubscribe) that:
Stops the event loop from executing.
Prevents handling of WebSocket connections or Redis messages in real-time.
Lacks proper asynchronous integration with the Ratchet loop.
Additionally, Laravel and Ratchet may be connected to different Redis instances, ports, or databases, which should be verified.
Solution
Use an Asynchronous Redis Client Compatible with the Ratchet Event Loop
The correct way to receive Redis messages in a non-blocking way is by using the react/redis package, which is fully compatible with the Ratchet event loop (ReactPHP). This allows the WebSocket server to simultaneously listen to Redis and handle WebSocket client connections.
Step-by-Step Implementation
1. Install Required Packages
Install react/redis and Ratchet (if not already installed):
composer require clue/redis-react
composer require cboden/ratchet
2. Update Your WebSocket Server
Here is a simplified example of a WebSocket server using Ratchet and react/redis to handle Redis messages and broadcast them to WebSocket clients:
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use React\EventLoop\Factory as LoopFactory;
use React\Socket\Server as SocketServer;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Clue\React\Redis\Factory as RedisFactory;
class StockOpnameServer implements MessageComponentInterface
{
public $clients;
public function __construct()
{
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
}
public function onMessage(ConnectionInterface $from, $msg) {}
public function onClose(ConnectionInterface $conn)
{
$this->clients->detach($conn);
}
public function onError(ConnectionInterface $conn, \Exception $e)
{
$conn->close();
}
public function broadcast($data)
{
foreach ($this->clients as $client) {
$client->send($data);
}
}
}
// Create ReactPHP loop
$loop = LoopFactory::create();
// Create the WebSocket server instance
$stockServer = new StockOpnameServer();
// Set up WebSocket server
$socket = new SocketServer('0.0.0.0:8080', $loop);
$server = new IoServer(
new HttpServer(
new WsServer($stockServer)
),
$socket,
$loop
);
// Subscribe to Redis
$redisFactory = new RedisFactory($loop);
$redisFactory->createSubscriber('127.0.0.1:6379')->then(function ($redis) use ($stockServer) {
$redis->psubscribe('stock-opname.*');
$redis->on('pmessage', function ($pattern, $channel, $message) use ($stockServer) {
$stockServer->broadcast($message);
});
});
// Run the loop
$loop->run();
This example:
Starts a WebSocket server.
Subscribes to all Redis channels that match stock-opname.*.
Forwards any Redis message received to all connected WebSocket clients.
3. Verify Laravel Redis Configuration
Ensure that Laravel and your WebSocket server are using the same Redis configuration (host, port, database index):
Check in Laravel: config/database.php
'redis' => [
'client' => 'phpredis',
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
],
Ensure that REDIS_HOST, REDIS_PORT, and REDIS_DB match what the WebSocket server is using.
Checklist
Use react/redis in the WebSocket server.
Ensure Laravel and the WebSocket server use the same Redis instance.
Integrate Redis subscription into the same event loop as Ratchet.
Replace blocking psubscribe() with async handling from react/redis.
Confirm Redis::publish() sends to correct channel (e.g., stock-opname.branch1).
Confirm Redis receives messages by testing with redis-cli.