Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ratchet Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation

    composer require ad3n/ratchet-bundle
    

    Ensure your project uses Symfony 4.4+ or 5.x (compatible with Ratchet 0.4.x).

  2. Configure the Bundle Add the bundle to config/bundles.php:

    return [
        // ...
        Ihsan\RatchetBundle\IhsanRatchetBundle::class => ['all' => true],
    ];
    
  3. 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' }
    
  4. Set the WebSocket Port Configure via .env or config/packages/ihsan_ratchet.yaml:

    ihsan_ratchet:
        web_socket_port: 8080
    
  5. Start the Server

    php bin/console ihsan:server:start
    

    Verify the server is running on ws://localhost:8080.


First Use Case: Echo Server

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).


Implementation Patterns

Core Workflows

  1. Processor Lifecycle

    • Processors are instantiated once per server start and reused for all connections.
    • Avoid storing connection-specific state in the processor; use the ConnectionInterface object passed to process() for per-client data.
  2. Message Handling

    • Input: Messages are wrapped in Ihsan\RatchetBundle\Message\Message objects. Access raw data via $message->getData().
    • Output: Return a Message object (original or new) to send a response. Use json_encode() for structured data.
    • Example:
      return new Message(json_encode([
          'status' => 'success',
          'data' => $processedData,
      ]));
      
  3. Connection Management

    • Use ConnectionInterface methods to interact with clients:
      • $connection->send($data): Send data directly (bypassing processors).
      • $connection->close(): Terminate the connection.
    • Listen for connection events via Ratchet\Wamp\Topic or custom logic in the processor.
  4. Dependency Injection

    • Inject services into processors via constructor arguments. The bundle auto-wires tagged services.
    • Example:
      public function __construct(private MyService $service) {}
      
  5. Routing Messages

    • Use the Message object’s metadata (e.g., $message->getHeaders()) to route messages to different processors or services.
    • Example:
      if ($message->getData() === 'ping') {
          return new Message('pong');
      }
      

Integration Tips

  1. Symfony Integration

    • Access Symfony services (e.g., Doctrine, HTTP client) in processors:
      public function __construct(private EntityManagerInterface $em) {}
      
    • Use ContainerAwareInterface if needed (though auto-wiring is preferred).
  2. Authentication

    • Validate connections on process() by checking headers or payloads:
      if (!$this->authService->validate($connection, $message)) {
          $connection->close();
      }
      
    • Store authenticated user data in the connection object for later use:
      $connection->user = $user; // Custom property
      
  3. Broadcasting

    • To broadcast to all clients, iterate over the 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'));
          }
      });
      
    • Note: Requires access to the server instance (see "Gotchas").
  4. Asynchronous Tasks

    • Offload heavy processing to Symfony’s message bus or queues:
      $this->messageBus->dispatch(new ProcessMessage($message->getData()));
      return new Message('Processing started');
      
  5. Configuration

    • Override default settings (e.g., port, host) in config/packages/ihsan_ratchet.yaml:
      ihsan_ratchet:
          web_socket_port: 8080
          web_socket_host: 0.0.0.0  # Bind to all interfaces
      

Gotchas and Tips

Pitfalls

  1. Server Instance Access

    • Gotcha: Processors do not receive the 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
      
    • Tip: Register a command to trigger broadcasts:
      $this->broadcaster->sendToAll('Hello, everyone!');
      
  2. Connection Leaks

    • Gotcha: Unclosed connections can exhaust server resources. Always call $connection->close() when done.
    • Tip: Use a finally block or event listeners to ensure cleanup:
      try {
          // Process message
      } finally {
          if ($shouldClose) {
              $connection->close();
          }
      }
      
  3. Message Size Limits

    • Gotcha: Ratchet has default limits (e.g., 16KB for messages). Large payloads may be truncated.
    • Tip: Configure limits in the Ratchet server or split data into chunks.
  4. Thread Safety

    • Gotcha: Processors are not thread-safe by default. Avoid shared mutable state.
    • Tip: Use Symfony’s lock services or connection-specific storage (e.g., $connection->customData).
  5. Configuration Overrides

    • Gotcha: .env variables may not override config/packages/ settings if not prefixed correctly. Use:
      IHSAN_RATCHET_WEB_SOCKET_PORT=8080
      
    • Tip: Check the bundle’s DependencyInjection class for supported parameters.

Debugging

  1. Logs

    • Enable debug mode in config/packages/dev/ihsan_ratchet.yaml:
      ihsan_ratchet:
          debug: true
      
    • Log messages in processors:
      $this->logger->info('Processing message', ['data' => $message->getData()]);
      
  2. Connection Drops

    • Use Ratchet\ConnectionInterface events:
      $connection->on('close', function () {
          $this->logger->info('Connection closed');
      });
      
  3. Port Conflicts

    • Ensure the port is free. Use lsof -i :8080 (Linux/macOS) or netstat -ano | findstr 8080 (Windows) to check.

Extension Points

  1. Custom Protocols

    • Extend the bundle by creating a custom Ratchet\Wamp\Topic or protocol handler. Override the bundle’s ServerFactory to inject your logic.
  2. Middleware

    • Add middleware to processors for cross-cutting concerns (e.g., logging, auth):
      public function process(ConnectionInterface $connection, Message $message): Message {
          $this->middleware->handle($connection, $message);
          return $this->coreLogic->process($connection, $message);
      }
      
  3. Event Dispatching

    • Dispatch Symfony events (e.g., KernelEvents::REQUEST) from processors to integrate with other bundles:
      $this->eventDispatcher->dispatch(new WebSocketMessageEvent($connection, $message));
      
  4. Testing

    • Mock ConnectionInterface for unit tests:
      $connection = $this->createMock(ConnectionInterface::class);
      $connection->method('send')->willReturn(true);
      $processor->process($connection, new Message('test'));
      
    • Use Ratchet\Client\Connector for integration tests:
      $connector = new Connector(new Ws
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle