Optional parameter $payload (and $event) declared before required
parameter $socketIds is implicitly treated as required by PHP 8.4+,
emitting a deprecation on every class load:
PHP Deprecated: Optional parameter $payload declared before
required parameter $socketIds is implicitly treated as a required
parameter
Made $socketIds optional (= []) — empty matches no connections via
array_flip lookup, so callers that intentionally omit it get a no-op
which preserves the practical contract (you can't whisper to nobody).
All four parameters are now optional. No call-site changes needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Handler::cacheAuthenticatedUser() and ::cleanupChannelConnections() were
writing/forgetting ws_socket_auth_<rawSocketId> while
WebsocketService::getAuth() and ::setUserAuthed() have always slugged
("123.456" → "123-456"). Result: the cache write was reachable from the
package's own writer path but not from the service-layer reader, so the
admin tooling (websockets:watch -v) saw cache misses and rendered #<id>
instead of the configured IdentityFormatter output.
Also: WatchStats now batch-loads missing users via the configured auth
provider model in one query per render, so the User column still renders
the full formatter shape even when the per-socket cache blob predates
the writer or got evicted.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
websockets:watch -v now delegates User-column rendering to a bound
IdentityFormatter. The package ships DefaultIdentityFormatter which
produces #<id> - <name> | <username> - <email> for typical Eloquent users
(any field absent = that segment dropped). Apps with non-User auth
subjects (Company, ApiClient, multi-tenant blobs) can implement the
contract and either bind it in their service provider or name it in
config/websockets.php as 'identity_formatter'. Resolution order is:
explicit container binding > config class > package default.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Verbose mode reuses Symfony's built-in -v flag (the short option is
reserved, so a custom one can't be added). Each channel summary is
followed by sub-rows showing the socket id, the authed user (falling
back to "Guest" or the user id if the user blob expired), and how long
the connection has been open.
Connection start times are written by Handler::establishConnection() into
ws_connection_<slug(socketId)> on open and forgotten on close. Also
fixed a latent bug in finalizeConnectionClose() where the forget key was
missing the slug() call that the reader has always used — previously
invisible because nothing wrote the key, now load-bearing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Renders the same Live Stats / channels table that `websockets:info` shows
at the bottom, but loops indefinitely so it can be left open as a quick
status pane. 1-second poll against the existing WebsocketService cache
reads — no pub/sub plumbing because there is no "stats changed" event
emitted today and a 1s tick is fast enough for the granularity humans
care about.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The legacy `websockets:restart` and `websocket:steer restart` rely on the
running server polling a cache key every ~5s, then unwinding the loop.
That fails silently when the cache driver differs across processes, the
poll loop stalls, or the deploy script needs to confirm the restart
happened. This adds a command that pgreps the running process, sends
SIGTERM directly (the existing PCNTL handler in StartServer already
catches it), then waits for supervisord's autorestart to bring up a new
PID before returning. Designed to be invoked from deploy scripts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Send 'websocket' to list all controllers with methods and metadata
- Send 'auth' to list all methods on AuthController
- Shows need_auth, lifecycle hooks (boot/booted/unboot) per controller
- Only enabled in local env or via WEBSOCKET_INTROSPECTION=true
- Never active in production unless explicitly enabled
- Introduced `helpers-and-testing.md` to document global helpers and WebsocketService class usage.
- Created `HandlerLifecycleTest.php` to test the full WebSocket handler lifecycle, including connection management, channel subscriptions, and message routing.
- Added `WebsocketServiceTest.php` to validate state tracking methods in WebsocketService, covering user authentication, channel tracking, and broadcast functionality.