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

Websocket Bundle Laravel Package

varspool/websocket-bundle

Symfony bundle integrating Ratchet WebSockets into Symfony apps. Provides a configurable WebSocket server, WAMP pub/sub routing, session and origin handling, and service-container-backed handlers for building real-time PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you composer require anything, understand what you're holding: this is a Symfony 2 bundle, not a Laravel package. There is no service provider, no facade, no config file in config/. What you actually get is three reusable ideas wrapped in Symfony glue:

  1. A long-running websocket server built on Wrench (a pure-PHP RFC 6455 implementation), launched from a Symfony console command (typically websocket:server — confirm with app/console list).
  2. Multiplexing over the WAMP sub-protocol: clients connect once and subscribe to topics (prefix + topic), so one socket carries many logical channels.
  3. A publish path — a container service (roughly websocket.publisher) that lets ordinary request/response code push a message into a topic the server is holding open.

So your mental model as a Laravel dev is: artisan command + broadcast driver. That's the whole value proposition.

Read in this order (clone the repo, don't install it yet):

  • README.md — the config sample and the demo client are the real spec.
  • DependencyInjection/Configuration.php — the authoritative config tree; README examples drift from version to version.
  • Command/ — find the server command, note its options (--port, verbosity).
  • Server/ — the Wrench Application implementation, TopicManager, and the pub/sub adapters. This is 80% of the code you'd ever port.
  • Resources/public/js/ — the bundled JS client shows exactly which WAMP frames the server expects.

Minimal smoke test (do this in a scratch Symfony 2.8 app on a PHP 5.6/7.0 container, not your Laravel app — dependency resolution against modern Symfony will refuse):

# app/config/config.yml — illustrative; verify keys against Configuration.php
websocket:
    server:
        host: 0.0.0.0
        port: 8080
app/console websocket:server -v
// the second argument matters: you must negotiate the 'wamp' subprotocol
const ws = new WebSocket('ws://localhost:8080/', 'wamp');
ws.onopen = () => {
  ws.send(JSON.stringify({ type: 'prefix', prefix: 'chat' }));
  ws.send(JSON.stringify({ type: 'subscribe', topic: 'room/1' }));
};
ws.onmessage = (e) => console.log(JSON.parse(e.data));

Your first real use case: a per-user notification feed. Browser subscribes to user/42/notifications; a Laravel listener publishes to the same topic when something happens. If that works end to end, everything else is polish.

Implementation Patterns

1. Sidecar (recommended if you must use the code as-is). Run the bundle in a tiny Symfony 2 app (or a standalone PHP script that boots only Wrench + TopicManager) under Supervisor. Laravel never loads the bundle; it only publishes. This keeps the abandoned Symfony 2 dependency tree out of your composer.json entirely.

2. Extraction (recommended if you want to keep it). Copy Server/, TopicManager, and the pub/sub adapters into app/Websockets/, delete every use Symfony\... and ContainerAware reference, and wrap it in an artisan command:

// app/Console/Commands/WebsocketServer.php
class WebsocketServer extends Command
{
    protected $signature = 'ws:serve {--port=8080} {--host=0.0.0.0}';

    public function handle()
    {
        $server = new Server('0.0.0.0', $this->option('port'));
        $server->registerApplication('topic', new TopicApplication(new TopicManager($this->laravel['log'])));
        $server->run(); // blocking; Supervisor restarts it
    }
}

3. Publish from Laravel. The bundle's publisher service normally talks to the running server process out-of-band (ZMQ or a Redis-style adapter, depending on version/config). In Laravel, build a one-method client that speaks the same wire format and bind it in a service provider so events can fire-and-forget:

// app/Events/OrderShipped.php -> listener
app(WebsocketPublisher::class)->publish("user/{$order->user_id}/notifications", [
    'type'  => 'order.shipped',
    'order' => $order->id,
]);

Dispatch from a queued listener, not from the request cycle — a dead websocket server must never fail a checkout.

4. Topic naming discipline. Use hierarchical, query-friendly names (user/{id}/notifications, room/{id}/messages) and set a prefix per connection. Treat the topic string as a public API: renaming it silently breaks every open browser tab.

5. Auth across the framework boundary. The server process has no session, so Auth::user() does not exist there. Issue a short-lived signed token in Laravel, pass it in the connection URL or the subprotocol header, and verify it inside onOpen before letting the client subscribe. Reject (close with a policy code) rather than silently ignoring.

6. Reconnect on the client. Always implement exponential-backoff reconnect and re-subscribe on onopen; PHP servers do die and deploys will restart them.

7. Behind nginx, terminate TLS and add the upgrade dance:

location /ws/ {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

Gotchas and Tips

  • It won't install on a modern Laravel app. Symfony 2-era constraints, PHP 5.x idioms, and a Wrench version that predates PHP 8. Expect fatal errors on each(), untyped ArrayAccess, and deprecated curly-brace string offsets if you force it in. Extraction or sidecar is the only sane path.
  • Subprotocol negotiation is the #1 silent failure. Connect without 'wamp' as the second WebSocket argument and you get the echo/plain application — the socket opens fine, subscriptions just never work. If "nothing happens," check this first.
  • Publishing from a web request does nothing without the bridge. The topic registry lives in the server process's memory. A fresh container in php-fpm has an empty registry. You must use the out-of-band publisher adapter; the in-memory/null one is a no-op from another process. This trips up nearly everyone once.
  • One process, one thread, blocking I/O. A slow onPublish/onData handler stalls every connected client. Keep handlers trivial: validate, enqueue, return. Push real work onto a Laravel queue worker.
  • Memory leaks in long-lived scripts. Per-connection objects, accumulating listeners, and unbounded logs will balloon a process that runs for weeks. unset connection state on close, cap any per-topic buffers, and let Supervisor recycle the process daily.
  • Origin checking defaults bite. If the server validates origins, an app on a different host/port (:8000 dev, wss:// prod) gets a handshake 400 or an immediate close. Either configure allowed origins explicitly or disable the check and enforce auth yourself — never rely on origin alone for security.
  • No native TLS. Wrench speaks plain ws://. Terminate at the proxy and make sure your origin check (if enabled) accounts for the X-Forwarded-Proto being https while the server sees http.
  • Config changes need a restart. The server reads configuration at boot; cache:clear alone leaves the old listener running. Bake "restart websocket worker" into your deploy script.
  • Debugging: run with -v/-vvv, watch for the Sec-WebSocket-Key handshake exchange, and use lsof -i :8080 when the port is inexplicably busy from a crashed prior run. websocat ws://localhost:8080/ -s wamp is far better than console.log for protocol issues.
  • Proxies and idle timeouts kill quiet sockets. Send periodic ping frames (or app-level heartbeats) every 20–30s and set proxy_read_timeout high on both nginx and any cloud LB.
  • Extension points worth knowing: implement Wrench's Application interface for custom behaviour (override onOpen/onClose/onData), and swap the TopicManager/pub-sub adapter for Redis-backed fan-out if you ever need more than one server process.
  • Honest context check: 49 stars, 0 dependents, last touched years ago. For a new Laravel project the equivalents — Laravel Reverb, Soketi, or Ratchet via a package — give you first-class auth, scaling, and PHP 8 support. Use this bundle only to maintain something already running on it, or as a compact reference implementation for "what does a topic-multiplexed PHP websocket server look like."
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle