ad3n/ratchet-bundle
Symfony bundle integrating Ratchet WebSockets. Define a MessageProcessor service (tag ihsan_ratchet.message_processor) to handle client messages, configure WEB_SOCKET_PORT/ihsan_ratchet.web_socket_port, then start the server with ihsan:server:start.
Installation
composer require ad3n/ratchet-bundle
Ensure your project uses Symfony 4.4+ or 5.x (compatible with Ratchet 0.4.x).
Configure the Bundle
Add the bundle to config/bundles.php:
return [
// ...
Ihsan\RatchetBundle\IhsanRatchetBundle::class => ['all' => true],
];
Define a Message Processor
Create a class implementing MessageProcessorInterface (as shown in the README) and tag it in config/services.yaml:
services:
App\Message\Processor\MyProcessor:
tags:
- { name: 'ihsan_ratchet.message_processor' }
Set the WebSocket Port
Configure via .env or config/packages/ihsan_ratchet.yaml:
ihsan_ratchet:
web_socket_port: 8080
Start the Server
php bin/console ihsan:server:start
Verify the server is running on ws://localhost:8080.
Create a processor to echo incoming messages:
// src/Message/Processor/EchoProcessor.php
namespace App\Message\Processor;
use Ihsan\RatchetBundle\Message\Message;
use Ihsan\RatchetBundle\Processor\MessageProcessorInterface;
use Ratchet\ConnectionInterface;
class EchoProcessor implements MessageProcessorInterface
{
public function process(ConnectionInterface $connection, Message $message): Message
{
return new Message($message->getData()); // Echo back
}
}
Tag it in services.yaml and restart the server. Test with a WebSocket client (e.g., browser JS or wscat).
Processor Lifecycle
ConnectionInterface object passed to process() for per-client data.Message Handling
Ihsan\RatchetBundle\Message\Message objects. Access raw data via $message->getData().Message object (original or new) to send a response. Use json_encode() for structured data.return new Message(json_encode([
'status' => 'success',
'data' => $processedData,
]));
Connection Management
ConnectionInterface methods to interact with clients:
$connection->send($data): Send data directly (bypassing processors).$connection->close(): Terminate the connection.Ratchet\Wamp\Topic or custom logic in the processor.Dependency Injection
public function __construct(private MyService $service) {}
Routing Messages
Message object’s metadata (e.g., $message->getHeaders()) to route messages to different processors or services.if ($message->getData() === 'ping') {
return new Message('pong');
}
Symfony Integration
public function __construct(private EntityManagerInterface $em) {}
ContainerAwareInterface if needed (though auto-wiring is preferred).Authentication
process() by checking headers or payloads:
if (!$this->authService->validate($connection, $message)) {
$connection->close();
}
$connection->user = $user; // Custom property
Broadcasting
Ratchet\ConnectionInterface collection (injected via Ratchet\Server\ServerInterface):
$server->loop->addPeriodicTimer(1, function () use ($server) {
foreach ($server->connections as $connection) {
$connection->send('Server time: ' . date('H:i:s'));
}
});
Asynchronous Tasks
$this->messageBus->dispatch(new ProcessMessage($message->getData()));
return new Message('Processing started');
Configuration
config/packages/ihsan_ratchet.yaml:
ihsan_ratchet:
web_socket_port: 8080
web_socket_host: 0.0.0.0 # Bind to all interfaces
Server Instance Access
ServerInterface directly. To broadcast or access all connections, inject the server via a service or use a static reference (not recommended). Instead, use a dedicated service:
services:
App\Service\WebSocketBroadcaster:
arguments:
- '@ihsan_ratchet.server' # Injected by the bundle
$this->broadcaster->sendToAll('Hello, everyone!');
Connection Leaks
$connection->close() when done.finally block or event listeners to ensure cleanup:
try {
// Process message
} finally {
if ($shouldClose) {
$connection->close();
}
}
Message Size Limits
Thread Safety
$connection->customData).Configuration Overrides
.env variables may not override config/packages/ settings if not prefixed correctly. Use:
IHSAN_RATCHET_WEB_SOCKET_PORT=8080
DependencyInjection class for supported parameters.Logs
config/packages/dev/ihsan_ratchet.yaml:
ihsan_ratchet:
debug: true
$this->logger->info('Processing message', ['data' => $message->getData()]);
Connection Drops
Ratchet\ConnectionInterface events:
$connection->on('close', function () {
$this->logger->info('Connection closed');
});
Port Conflicts
lsof -i :8080 (Linux/macOS) or netstat -ano | findstr 8080 (Windows) to check.Custom Protocols
Ratchet\Wamp\Topic or protocol handler. Override the bundle’s ServerFactory to inject your logic.Middleware
public function process(ConnectionInterface $connection, Message $message): Message {
$this->middleware->handle($connection, $message);
return $this->coreLogic->process($connection, $message);
}
Event Dispatching
KernelEvents::REQUEST) from processors to integrate with other bundles:
$this->eventDispatcher->dispatch(new WebSocketMessageEvent($connection, $message));
Testing
ConnectionInterface for unit tests:
$connection = $this->createMock(ConnectionInterface::class);
$connection->method('send')->willReturn(true);
$processor->process($connection, new Message('test'));
Ratchet\Client\Connector for integration tests:
$connector = new Connector(new Ws
How can I help you explore Laravel packages today?