API Index — Namespaces, Packages, Reports, Indices
Chatroom
in package
Lesson 22 — multi-room group chat (SQLite persistence, no Redis required).
Three pure-PHP responsibilities:
- Persist messages in the local SQLite (
chatroom_messagestable). - Recall the last N messages on join (so a refresh shows history).
- List the rooms that have any traffic (the "lobby" view).
Fan-out to connected sockets is the WS handler's job (route/learn_chatroom.php).
Single-server uses a local fd map; the lesson shows how to swap that for
WSRouter::room() to scale to N nodes — same call sites, different fabric.
Table of Contents
Constants
- DEFAULT_TAIL : mixed = 50
- MAX_MESSAGE_LEN : mixed = 2000
- MAX_USERNAME_LEN : mixed = 32
Methods
- broadcast_to_room() : void
- Fan-out helper: iterate the cluster-wide
chatroom_fdsStore table and push to every fd whose row'sroommatches. Works across workers (any worker can call$server->push($fd, ...)for any fd) AND across the cluster when the Store backend is Redis (the table iteration spans every node — federated chat for free). - listRooms() : array<int, array{room: string, last_msg_at: int, count: int}>
- Lobby — every room with at least one message + the latest activity timestamp.
- recent() : array<int, array{id: int, room: string, username: string, body: string, kind: string, created_at: int}>
- Last $tail messages from this room in chronological order (oldest first).
- saveMessage() : array{id: int, room: string, username: string, body: string, kind: string, created_at: int}
- Persist a message in the room. Trims user content + rejects empty bodies.
- asInt() : int
- Coerce a mixed PDO column value to
int, returning0on non-numeric input. - asString() : string
- Coerce a mixed PDO column value to
string, returning''on non-scalar input. - normalize() : array{0: string, 1: string, 2: string}
- Trim and clamp all three string inputs.
- shapeMessage() : array{id: int, room: string, username: string, body: string, kind: string, created_at: int}
Constants
DEFAULT_TAIL
private
mixed
DEFAULT_TAIL
= 50
MAX_MESSAGE_LEN
private
mixed
MAX_MESSAGE_LEN
= 2000
MAX_USERNAME_LEN
private
mixed
MAX_USERNAME_LEN
= 32
Methods
broadcast_to_room()
Fan-out helper: iterate the cluster-wide chatroom_fds Store table and
push to every fd whose row's room matches. Works across workers (any
worker can call $server->push($fd, ...) for any fd) AND across the
cluster when the Store backend is Redis (the table iteration spans every
node — federated chat for free).
public
static broadcast_to_room(mixed $server, string $room, array<string, mixed> $payload[, int $excludeFd = 0 ]) : void
Parameters
- $server : mixed
- $room : string
- $payload : array<string, mixed>
-
JSON-serialisable message payload.
- $excludeFd : int = 0
listRooms()
Lobby — every room with at least one message + the latest activity timestamp.
public
static listRooms() : array<int, array{room: string, last_msg_at: int, count: int}>
Return values
array<int, array{room: string, last_msg_at: int, count: int}>recent()
Last $tail messages from this room in chronological order (oldest first).
public
static recent(string $room[, int $tail = self::DEFAULT_TAIL ]) : array<int, array{id: int, room: string, username: string, body: string, kind: string, created_at: int}>
Parameters
- $room : string
- $tail : int = self::DEFAULT_TAIL
Return values
array<int, array{id: int, room: string, username: string, body: string, kind: string, created_at: int}>saveMessage()
Persist a message in the room. Trims user content + rejects empty bodies.
public
static saveMessage(string $room, string $username, string $body[, string $kind = 'message' ]) : array{id: int, room: string, username: string, body: string, kind: string, created_at: int}
Returns the persisted row (with assigned id + server-side timestamp).
Parameters
- $room : string
- $username : string
- $body : string
- $kind : string = 'message'
Return values
array{id: int, room: string, username: string, body: string, kind: string, created_at: int}asInt()
Coerce a mixed PDO column value to int, returning 0 on non-numeric input.
private
static asInt(mixed $v) : int
Parameters
- $v : mixed
Return values
intasString()
Coerce a mixed PDO column value to string, returning '' on non-scalar input.
private
static asString(mixed $v) : string
Parameters
- $v : mixed
Return values
stringnormalize()
Trim and clamp all three string inputs.
private
static normalize(string $room, string $username, string $body) : array{0: string, 1: string, 2: string}
$room defaults to 'general' when empty; $username defaults to
'anonymous'. Both $username and $body are truncated to
MAX_USERNAME_LEN and MAX_MESSAGE_LEN characters respectively.
Parameters
- $room : string
- $username : string
- $body : string
Return values
array{0: string, 1: string, 2: string} —Trimmed [room, username, body].
shapeMessage()
private
static shapeMessage(array<int|string, mixed> $row) : array{id: int, room: string, username: string, body: string, kind: string, created_at: int}
Parameters
- $row : array<int|string, mixed>