Go to file
Fabian @ Blax Software 9dc34d5c10 fix(hot-reload): keep the event dispatcher in the message child
The dev hot reload forgot the `events` instance, so the container rebuilt an
empty dispatcher and every listener the service providers registered was
gone for that message. Events fired from WS controllers reached nobody (a
shop's "order paid" mails and invoice silently never happened in dev).
Model observers kept working, which hid it: Eloquent holds its own
reference to the old dispatcher.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 12:56:37 +02:00
.github docs: add copilot instructions 2026-04-16 08:27:28 +02:00
config F IdentityFormatter contract — apps override how the User column renders 2026-04-27 13:50:22 +02:00
database/migrations Renovation 2025-01-16 08:54:02 +01:00
docs docs(agents): add AGENTS.md source-verified reference + fix stale wsSession/install docs 2026-06-30 10:56:25 +02:00
resources/views Merge 2.x changes (#1043) 2022-10-06 13:46:54 +02:00
routes A default broadcasting route, I ip on close 2025-12-05 19:56:44 +01:00
src fix(hot-reload): keep the event dispatcher in the message child 2026-09-25 12:56:37 +02:00
tests fix(hot-reload): keep the event dispatcher in the message child 2026-09-25 12:56:37 +02:00
.codecov.yml Addded .codecov.yml 2020-08-23 13:54:22 +03:00
.editorconfig wip 2020-09-10 22:59:26 +03:00
.gitattributes Update .gitattributes 2020-06-02 11:26:55 +02:00
.gitignore wip 2020-09-10 22:59:26 +03:00
.scrutinizer.yml wip 2020-09-10 22:59:26 +03:00
.styleci.yml wip 2020-09-10 22:59:26 +03:00
AGENTS.md docs(agents): add AGENTS.md source-verified reference + fix stale wsSession/install docs 2026-06-30 10:56:25 +02:00
CONTRIBUTING.md initial commit 2018-11-20 09:54:06 +01:00
LICENSE wip 2020-09-10 22:59:26 +03:00
README.md docs(agents): add AGENTS.md source-verified reference + fix stale wsSession/install docs 2026-06-30 10:56:25 +02:00
composer.json IA helpers 2026-02-03 15:03:50 +01:00
phpunit.xml I performance, A testing & event-driven 2026-01-24 13:34:29 +01:00

README.md

Blax Software OSS

Laravel WebSockets

PHP Version Laravel

Plug-and-play WebSockets for Laravel with a Pusher-compatible protocol, async fork-based handling, attribute-driven routing, and live operational tooling.

[!NOTE] This package is actively maintained as a fork of beyondcode/laravel-websockets.

Features

  • #[Websocket] attribute on regular HTTP controllers — turn any controller method into a WebSocket-callable endpoint with one annotation, no second class to maintain

  • Async processing — incoming messages are handled in pcntl_fork child processes, so a slow handler never blocks the event loop

  • Broadcast from anywhere — ws_broadcast(), ws_whisper(), ws_broadcast_except() helpers and a static WebsocketService API let any controller, job, or service push events to any channel

  • Multiple channel types — public, private-*, presence-*, and open-presence-* channels with the standard auth handshake

  • Live ops tooling — php artisan websockets:watch renders connection counts, authenticated users, and per-channel connections, refreshing every second:

    WebSocket Server — Live Stats
    2026-05-05 14:33:35 — refreshing every 1s (Ctrl+C to exit)
    
      Live Stats .......................................................................................................................................
      Total connections ............................................................................................................................. 12
      Authenticated users ............................................................................................................................ 3
      Active channels ................................................................................................................................ 1
    
    +-----------+-------------+
    | Channel   | Connections |
    +-----------+-------------+
    | websocket | 12          |
    +-----------+-------------+
    
  • Automatic route recognition — controller class and method names map to event names automatically (FlightschoolController::index → flightschool.index); override per method or per class via #[Websocket(event: ..., prefix: ..., suffix: ..., needAuth: true)]

  • Hot code reload in dev, OPcache in prod — websocket:steer cache:clear clears OPcache and the controller resolver cache without restarting the running server, so iteration is instant in development while production runs with fully warmed caches

  • Pusher-compatible protocol — supports both modern websocket.* and legacy pusher:* action formats, drop-in for Echo and pusher-js clients

  • Test helpers — newConnection(), newActiveConnection(), newPrivateConnection(), newPresenceConnection(), plus assertSentEvent() keep WebSocket tests short

Requirements

  • PHP 8.1+
  • Laravel 9, 10, 11 or 12
  • ext-pcntl (for async fork-based handling)

Installation

composer require blax-software/laravel-websockets

Publish the config:

php artisan vendor:publish --provider="BlaxSoftware\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"

Start the server:

php artisan websockets:serve

Default URL is ws://127.0.0.1:6001.

Quick Start

1. Mark a regular controller method as WebSocket-reachable

use BlaxSoftware\LaravelWebSockets\Attributes\Websocket;

class FlightschoolController extends Controller
{
    #[Websocket]                      // event: "flightschool.index"
    public function index() { ... }

    #[Websocket(event: 'flightschools.list')]   // explicit override
    public function list() { ... }

    #[Websocket(needAuth: true)]      // requires authenticated socket
    public function update() { ... }
}

2. Broadcast from anywhere

// Helpers
ws_broadcast('chat.message', ['text' => 'Hello'], 'chat');
ws_whisper('chat.typing', ['typing' => true], ['1234.1', '1234.2'], 'chat');
ws_broadcast_except('chat.message', ['text' => 'Server msg'], ['1234.1'], 'chat');

// Service API
use BlaxSoftware\LaravelWebSockets\Services\WebsocketService;

WebsocketService::send('metrics.tick', ['count' => 1], 'websocket');
WebsocketService::broadcastExcept('chat.message', ['text' => 'Hi'], ['1234.1'], 'chat');

3. Per-connection session store

Inside a WebSocket handler, wsSession() returns a Redis-backed key/value store scoped to the current connection that persists across messages on the same socket. It takes no arguments.

wsSession()->increment('transmit_count');
$count = wsSession()->get('transmit_count', 0);
wsSession()->put('last_action', 'transmitted');

4. Watch live stats

php artisan websockets:watch          # connection counts and channels
php artisan websockets:watch -v       # expanded per-connection rows
php artisan websockets:info           # one-shot snapshot

5. Iterate without restarting

php artisan websocket:steer cache:clear   # clear OPcache + resolver cache
php artisan websockets:restart            # graceful restart
php artisan websocket:restart-hard        # signal-based force restart

Channel Types

Type Prefix Description
Public (none) Anyone can subscribe
Private private- Server-signed auth required
Presence presence- Auth required, tracks user list, broadcasts join/leave
Open Presence open-presence- Presence semantics without the auth signature — useful for guests

Testing

$connection = $this->newActiveConnection(['chat']);

$this->wsHandler->onMessage($connection, new Message([
    'event' => 'websocket.ping',
    'data'  => new stdClass(),
]));

$connection->assertSentEvent('websocket.pong');
vendor/bin/phpunit --exclude-group=stability,stress,integration,requires-server

Documentation

Changelog

See CHANGELOG.

Security

Please report vulnerabilities via the issue tracker or by email: office@blax.at.

Credits

License

MIT. See LICENSE.md.

Star History

Star History Chart