From 1c0eefa16009f7919dff3c4cce23ba5ee58752d1 Mon Sep 17 00:00:00 2001 From: "Fabian @ Blax Software" Date: Tue, 5 May 2026 16:44:26 +0200 Subject: [PATCH] docs: rewrite README with feature overview, watch command, and star history Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 153 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 8084b10..1a8959a 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,152 @@ +[![Blax Software OSS](https://raw.githubusercontent.com/blax-software/laravel-workkit/master/art/oss-initiative-banner.svg)](https://github.com/blax-software) + # Laravel WebSockets +[![PHP Version](https://img.shields.io/badge/php-%5E8.1-blue)](https://php.net) +[![Laravel](https://img.shields.io/badge/laravel-9.x--12.x-orange)](https://laravel.com) + +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. -Plug-and-play WebSockets for Laravel with a Pusher-compatible protocol, a fast fork-based handler, and practical helpers for broadcasting and testing. +## Features -## Why this package +- **`#[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: -- Drop-in broadcasting backend for Laravel apps that already use Echo/Pusher-compatible clients -- Fast local handler with async processing via `pcntl_fork` -- Protocol compatibility for both modern `websocket.*` and legacy `pusher:*` action formats -- Built-in developer ergonomics: helper functions, service methods, and rich test helpers + ``` + WebSocket Server — Live Stats + 2026-05-05 14:33:35 — refreshing every 1s (Ctrl+C to exit) -## Install in 2 minutes + Live Stats ....................................................................................................................................... + Total connections ............................................................................................................................. 12 + Authenticated users ............................................................................................................................ 3 + Active channels ................................................................................................................................ 1 -1. Install package + +-----------+-------------+ + | 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 ```bash composer require blax-software/laravel-websockets ``` -2. Publish config +Publish the config: ```bash -php artisan vendor:publish --provider="BlaxSoftware\\LaravelWebSockets\\WebSocketsServiceProvider" --tag="config" +php artisan vendor:publish --provider="BlaxSoftware\LaravelWebSockets\WebSocketsServiceProvider" --tag="config" ``` -3. Start server +Start the server: ```bash php artisan websockets:serve ``` -Default server URL is `ws://127.0.0.1:6001`. +Default URL is `ws://127.0.0.1:6001`. -## Helper functions (broadcast from anywhere) +## Quick Start -The package ships with global helpers in `src/helpers_global.php`. +### 1. Mark a regular controller method as WebSocket-reachable ```php -// Broadcast to everyone on a channel -ws_broadcast('chat.message', ['text' => 'Hello'], 'chat'); +use BlaxSoftware\LaravelWebSockets\Attributes\Websocket; -// Whisper to specific socket IDs only -ws_whisper('chat.typing', ['typing' => true], ['1234.1', '1234.2'], 'chat'); +class FlightschoolController extends Controller +{ + #[Websocket] // event: "flightschool.index" + public function index() { ... } -// Broadcast to everyone except listed sockets -ws_broadcast_except('chat.message', ['text' => 'Server msg'], ['1234.1'], 'chat'); + #[Websocket(event: 'flightschools.list')] // explicit override + public function list() { ... } -// Check if local unix-socket broadcaster is available -if (ws_available()) { - ws_broadcast('app.health', ['ok' => true]); + #[Websocket(needAuth: true)] // requires authenticated socket + public function update() { ... } } - -// Build protocol auth payload for private/presence channels -$auth = wsSession('private-updates', ['user_id' => 7, 'user_info' => ['name' => 'Jane']]); ``` -## Service API - -Use the service directly when you prefer explicit class calls over helpers. +### 2. Broadcast from anywhere ```php +// 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::whisper('chat.typing', ['typing' => true], ['1234.1'], 'chat'); WebsocketService::broadcastExcept('chat.message', ['text' => 'Hi'], ['1234.1'], 'chat'); - -// Optional in-process tracking helpers -WebsocketService::setUserAuthed($socketId, $userId); -$authed = WebsocketService::getAuthedUsers(); ``` -## Testing experience +### 3. Build a private/presence auth payload -The test suite includes helper-first patterns so WebSocket tests stay short and readable. +```php +$auth = wsSession('private-updates', [ + 'user_id' => 7, + 'user_info' => ['name' => 'Jane'], +]); +``` -### Test helpers +### 4. Watch live stats -- `newConnection()` -- `newActiveConnection(['channel'])` -- `newPrivateConnection('private-channel')` -- `newPresenceConnection('presence-channel', ['user_id' => 1, 'user_info' => [...]])` +```bash +php artisan websockets:watch # connection counts and channels +php artisan websockets:watch -v # expanded per-connection rows +php artisan websockets:info # one-shot snapshot +``` -### Example +### 5. Iterate without restarting + +```bash +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 ```php $connection = $this->newActiveConnection(['chat']); $this->wsHandler->onMessage($connection, new Message([ - 'event' => 'websocket.ping', - 'data' => new stdClass(), + 'event' => 'websocket.ping', + 'data' => new stdClass(), ])); $connection->assertSentEvent('websocket.pong'); ``` -Run tests: - ```bash vendor/bin/phpunit --exclude-group=stability,stress,integration,requires-server ``` @@ -108,6 +156,7 @@ vendor/bin/phpunit --exclude-group=stability,stress,integration,requires-server - Main docs: [docs](docs) - Getting started: [docs/getting-started/introduction.md](docs/getting-started/introduction.md) - Helper & testing guide: [docs/advanced-usage/helpers-and-testing.md](docs/advanced-usage/helpers-and-testing.md) +- Custom handlers: [docs/advanced-usage/custom-websocket-handlers.md](docs/advanced-usage/custom-websocket-handlers.md) ## Changelog @@ -115,7 +164,7 @@ See [CHANGELOG](CHANGELOG.md). ## Security -Please report vulnerabilities via issue tracker or by email: office@blax.at. +Please report vulnerabilities via the issue tracker or by email: office@blax.at. ## Credits @@ -126,3 +175,13 @@ Please report vulnerabilities via issue tracker or by email: office@blax.at. ## License MIT. See [LICENSE.md](LICENSE.md). + +## Star History + + + + + + Star History Chart + +