Weave 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

p2/ratchet-bundle

A Symfony bundle that integrates the Ratchet WebSocket library, helping PHP developers add real-time, bidirectional communication to applications. It provides configuration and integration points for running WebSocket servers alongside Symfony.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the bundle with Composer (composer require p2/ratchet-bundle). It pulls in cboden/ratchet and expects a Symfony app that still registers bundles in a kernel (this is a Symfony 2/3-era package; on Symfony 4+ you may need config/bundles.php plus Flex-style config in config/packages/).
  2. Register the bundle — new P2\Bundle\RatchetBundle\P2RatchetBundle() in AppKernel::registerBundles() (or config/bundles.php on newer Symfony).
  3. Add minimal config — at minimum the listen address/port for the WebSocket server (a bind/port entry under the bundle's config key). Start with the loopback or a local dev port and only expose it behind a proxy later.
  4. Run the server — the bundle ships a console command that boots the Ratchet server while keeping the Symfony container available to your handlers. Run it in the foreground first with -vvv so you can see connection/chat traffic in your terminal.
  5. First use case — a single "echo/notification" channel: a JS WebSocket client connects to ws://localhost:<port>, sends a JSON message, and a tagged handler service in your app receives it and pushes a response back. This validates the whole chain (container → handler → connection) before you add auth, rooms, or broadcasting.

Where to look first:

  • The bundle's DependencyInjection/ folder to see the exact config keys and service IDs it registers.
  • The console command class — it shows how the server is constructed and how it gets the container.
  • The bundle's Resources/config/services.yml to learn which tags make a class a "message handler."
  • The README example (usually a Chat/Hello handler) — copy it verbatim into src/ and get it working before customizing.

Implementation Patterns

Handler services for message logic. The typical pattern is: you write a service that implements the bundle's message-handler interface, tag it (or implement the marker interface), and the bundle routes decoded client messages to it. Keep these handlers thin — parse the payload, call a domain service, return the response. Don't put business rules in the handler itself.

JSON envelope convention. Adopt a small message envelope like {"type": "...", "payload": {...}} and a single dispatcher handler that switches on type. This avoids one tagged handler per message and makes the client protocol explicit and versionable.

Broadcasting and rooms. For anything multi-user, keep an in-memory registry of connections → room/topic (an array or SplObjectStorage keyed by connection). Broadcast by iterating the room's connections and calling send(). For multi-process scaling you'll need a pub/sub backend (Redis) or a dedicated broker — the bundle itself only knows about connections in its own process.

Injecting Symfony services + resetting Doctrine. Handlers run inside the server process with the real container, so you can inject repositories and the EntityManager. In the handler, wrap DB work in try/finally and call $em->clear() (or reset the manager) after each message — the process is long-lived, so the identity map and stale entity state will otherwise cause subtle bugs.

Auth/session integration. The common approach is to read the Symfony session cookie during the WebSocket handshake ($conn->httpRequest / request headers), look up the session in the configured handler, and attach the resolved user to the connection object. Do the auth check once at handshake, not on every message, and keep the user ID on the connection for authorization decisions later.

Lifecycle hooks. Use the server's connection onOpen/onClose events for presence tracking, audit logging, and cleanup, and a periodic timer if you need heartbeats/ping-pong (proxies and browsers will drop idle sockets). Wire those through the bundle's server factory/event extension points rather than subclassing the whole server.

Running it like a daemon. In production, run the command under systemd or Supervisor with restart-on-crash, bind to 127.0.0.1, and terminate TLS/WSS at nginx (with Upgrade/Connection headers and a long proxy_read_timeout). Emit logs to stdout and let the supervisor collect them. Health-check by having the app connect to itself periodically.

Integration with the rest of Symfony. Treat the WebSocket server as a separate long-running worker of the same app: share the container and config, but push outbound notifications into it from HTTP requests via a queue or Redis pub/sub and have the server subscribe. Don't try to make the HTTP kernel call into the WS process directly.

Gotchas and Tips

  • Long-lived process state. Services, handlers, and the container are effectively singletons for the life of the server. Anything you cache on a handler (e.g., per-user data) persists across connections. Prefer stateless handlers and reset Doctrine/caches after each message.
  • Symfony version drift. This is an older bundle; on Symfony 4/5+ you'll likely need to adjust bundle registration and config loading manually. Check that the cboden/ratchet version pulled in is PHP-compatible with your runtime before committing.
  • Config keys are easy to get wrong. Confirm the exact key names from the bundle's Configuration.php — mismatches are usually silent (defaults apply), so you can spend an hour wondering why your port/bind change did nothing. Dump the resolved container (bin/console debug:container) to verify services and parameters.
  • Console command must run separately from PHP-FPM. It occupies its own process/port; don't try to spawn it from a request. On Windows, Ratchet's event loop behaves differently — test there early or use a Linux dev environment.
  • Reverse proxy is almost always required for WSS. Browsers on HTTPS can't connect to a ws:// endpoint, and mixed-content errors are opaque. If the JS client fails with no server-side log, suspect the proxy upgrade headers or the mixed-content block first.
  • Debugging: run with -vvv, add logging at the handler entry point, and use bin/console interactively. For connection issues, test with wscat or websocat before involving the browser so you can separate transport problems from client-code problems.
  • Error isolation. An uncaught exception inside a handler can take down or stall the server loop. Catch exceptions at the dispatcher level and send a structured error response to the client so the process keeps running.
  • Extension points to prefer over forks: custom server factory/service overrides via compiler pass, tagged handlers, and the server's event callbacks. Avoid editing vendor code — you can't upgrade it later, and composer will revert your patches.
  • Scale expectations. With 26 stars and no dependents, expect thin docs and no community support: read the source, pin versions in composer.lock, and if you need production-grade features (presence at scale, redis fan-out, HTTP push) consider comparing against Mercure or a maintained Swoole/RoadRunner stack before building deep on top of this bundle.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core