erfanvahabpour / laravel-swoole-ws
Laravel WebSocket server built on Swoole/OpenSwoole with routing, command protocols, scoped connections, channels, and Redis/Table-backed connection stores.
Installs: 17
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/erfanvahabpour/laravel-swoole-ws
Requires
- php: ^8.2
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
README
A high-performance WebSocket server library for Laravel powered by Swoole / OpenSwoole, designed for:
- Real-time applications
- IoT / device communication
- Command-based device protocols
- Channel & room broadcasting
- Scalable multi-connection state management (memory / table / Redis)
This package provides a Laravel-native DX while running outside the HTTP lifecycle.
โ ๏ธ Status: Under active development APIs are stabilizing, but breaking changes may occur.
Features
- ๐ Swoole / OpenSwoole WebSocket server
- ๐ Laravel service provider & facade
- ๐งญ WebSocket routing (
WS::route) - ๐ง Command-based device protocol (
WS::command,WS::response) - ๐ Handshake URL path scoping (
/pub/chat,/attendance, etc.) - ๐ Middleware support (
ws.auth, custom middleware) - ๐ฅ Channels & presence authorization
- ๐ก Broadcast to rooms / users
- ๐ Connection stores:
- In-memory
- Swoole\Table
- Redis (multi-server ready)
- ๐งช Testbench + PHPUnit support
- โ๏ธ Artisan commands (
ws:start,ws:stop,ws:reload)
Requirements
- PHP 8.2+
- Laravel 10+
- Swoole or OpenSwoole extension enabled
Check extension:
php -m | grep swoole php -m | grep openswoole
Installation
composer require erfanvahabpour/laravel-swoole-ws
Laravel auto-discovery is enabled.
Publish Config & Routes
php artisan vendor:publish --tag=ws-config php artisan vendor:publish --tag=ws-routes php artisan vendor:publish --tag=ws-channels
Files created:
config/ws.phproutes/ws.phproutes/ws_channels.php
Starting the WebSocket Server
php artisan ws:start
Default output:
WS server starting on 0.0.0.0:9502
Stop / reload:
php artisan ws:stop php artisan ws:reload
WebSocket Protocols Supported
This library supports two protocols at the same time:
1๏ธโฃ Legacy Route Protocol (WS::route)
Client message format
{
"path": "/chat",
"action": "send",
"data": { "text": "hello" },
"meta": {}
}
Route definition
use EFive\Ws\Facades\WS; WS::route('/chat', 'send', function ($ctx, $data) { return ['ok' => true]; });
Response format
{
"event": "ws.response",
"data": { "ok": true },
"meta": []
}
2๏ธโฃ Command / Device Protocol (WS::command)
Designed for IoT / terminal / attendance devices.
Client โ Server
{
"cmd": "reg",
"sn": "ABC123",
"version": "1.0"
}
Server โ Client (reply)
{
"ret": "reg",
"result": true,
"cloudtime": "2025-01-01 12:00:00"
}
Handshake Path Scoping (IMPORTANT)
Devices can connect using different WebSocket URLs:
ws://127.0.0.1:9502/pub/chat
ws://127.0.0.1:9502/attendance
The handshake path becomes a routing scope.
Why?
Different devices may use the same cmd names (reg, sendlog, etc.) but require different logic.
Scoped Command Routing
Define scoped commands
use EFive\Ws\Facades\WS; WS::scope('/pub/chat')->command('reg', function ($ctx, $payload) { return ['pong' => true]; }); WS::scope('/attendance')->command('reg', function ($ctx, $payload) { return [ 'device' => 'attendance', 'sn' => $payload['sn'] ?? null, ]; });
Client connects
wscat -c ws://127.0.0.1:9502/pub/chat
Send:
{"cmd":"reg"}
Response:
{"ret":"reg","result":true,"pong":true}
Automatic ret Replies
When handling WS::command:
-
If handler returns an array, it is automatically sent as:
{ "ret": "<cmd>", "result": true, ...payload } -
If handler calls
$ctx->replyRet(), returnnullto avoid double responses.
Example
WS::command('reg', fn () => ['pong' => true]);
โก automatically sends:
{"ret":"reg","result":true,"pong":true}
Manual Replies & Server Push
Manual reply
$ctx->replyRet('reg', true, ['cloudtime' => now()]);
Push command to client
$ctx->pushCmd('getuserlist', ['count' => 10]);
Middleware
Apply to routes
WS::route('/chat', 'send', $handler) ->middleware(['ws.auth']);
Built-in
ws.authโ token-based authentication
Authentication
Handshake token
ws://host:port/path?token=YOUR_TOKEN
Message token
{
"cmd": "reg",
"meta": { "auth": "TOKEN" }
}
Custom resolver (recommended)
config()->set('ws.auth.resolver', function (string $token) { return (object) ['id' => 1, 'name' => 'Device']; });
Channels & Presence
Define channels
routes/ws_channels.php
WS::channel('private-chat.{id}', function ($user, $id) { return true; });
Subscribe
{
"path": "/ws",
"action": "subscribe",
"data": { "channel": "private-chat.1" }
}
Connection Stores
Configured in config/ws.php.
Available drivers
memoryโ simple, single workertableโ fast shared memoryredisโ recommended for multi-server scaling
Redis example
'store' => [ 'driver' => 'redis', 'redis' => [ 'connection' => 'default', 'prefix' => 'ws:', 'ttl_seconds' => 86400, ], ],
Testing
vendor/bin/phpunit
Uses Orchestra Testbench.
CI
GitHub Actions included:
- PHP 8.2 / 8.3
- PHPUnit
Roadmap (v0.1.0)
- WebSocket routing
- Command protocol
- Handshake path scoping
- Redis connection store
- ws.auth middleware
- Subscribe / unsubscribe routes
- Presence broadcasting
- Rate limiting middleware
- Server metrics endpoint
- Binary protocol support
License
MIT ยฉ Erfan Vahabpour