Alpha ZealPHP is early-stage and under active development. APIs may change between minor versions until v1.0. Feedback and bug reports welcome on GitHub.
API Index — Namespaces, Packages, Reports, Indices

TableBackend
in package
implements StoreBackend

FinalYes

Default StoreBackend — wraps OpenSwoole\Table.

Lifts the existing static logic of ZealPHP\Store into instance methods so the facade in Task 10 can delegate. Public semantics (including the "graceful return on missing table" pattern from the current impl) are preserved verbatim.

Table of Contents

Interfaces

StoreBackend
Behavioural contract every Store backend implements.

Properties

$capacityWarned  : array<string, true>
$maxRows  : array<string, int>
$schemas  : array<string, array<string, array{0: int, 1?: int}>>
$tables  : array<string, Table>

Methods

clear()  : void
Delete all rows from the named table by iterating and deleting each key individually (no native bulk-delete on OpenSwoole\Table).
count()  : int
Return the number of rows in the named table, or 0 when the table doesn't exist.
decr()  : int|float
Atomically decrement column $col by $by. Returns the new column value (int/float per the column type), or 0 when the table doesn't exist.
del()  : bool
Delete a row by key. Returns false when the table doesn't exist or the key was already absent.
exists()  : bool
Return true when the named table contains a row with the given key.
get()  : mixed
Read a row or a single field from the named table. Returns null when the table or key doesn't exist. When $field is provided, returns the field's scalar value or null if absent.
incr()  : int|float
Atomically increment column $col by $by. Returns the new column value — int for an INT column, float for a FLOAT column (OpenSwoole\Table supports both) — or 0 when the table doesn't exist. Matches the StoreBackend::incr(): int|float contract. $by is passed through unchanged so a FLOAT column increments by a fractional amount (#420 — the old (int) $by cast truncated the step AND the narrow : int return type fatally rejected the float a FLOAT column returns).
iterate()  : Generator<string, array<string, scalar>>
Iterate all rows in the named table as a Generator. Yields string keys mapped to array<string, scalar> row arrays. Returns immediately when the table doesn't exist.
iteratePaged()  : array{cursor: string, rows: array>}
Paginated iteration. **O(N²/page) on the Table backend** — the cursor is a skip-offset and each call re-iterates from row 0, discarding $cursor rows before collecting the next $count. Paginating all N rows therefore costs O(N² / page). Fine for a few thousand rows; for large tables use the Redis/Tiered backend (true SCAN cursor) instead, or iterate() if you can hold one pass in memory. See the scaling-limits doc.
make()  : void
Create a named OpenSwoole\Table with the given schema. Each column in $columns is [TYPE_*, $size]. When $columns is empty, a single 'value' column of type TYPE_STRING(256) is created. $opts is accepted for interface compatibility but unused by this backend.
mget()  : array<string, array<string, scalar>|null>
Bulk read multiple rows. Missing keys are returned as null in the result map. Non-scalar column values are silently skipped (they cannot arise from a normal set() call on this backend).
mset()  : bool
Bulk write multiple rows by calling set() for each entry in sequence.
names()  : array<int, string>
Return the names of all tables registered via make().
rawTable()  : Table|null
Direct access to the underlying Table — used by the Store facade to keep Store::table($name) working under the table backend.
schema()  : array<string, array{0: int, 1?: int}>|null
Column schema as registered via make(). Exposed for tests + the future tiered backend; mirrors what RedisBackend stores internally for TypeCodec decoding.
set()  : bool
Write a row to the named table. Returns false when the table doesn't exist or when OpenSwoole\Table::set() fails — most commonly because the table is **full** (maxRows is a HARD boot-time cap with NO eviction, so every new distinct key past the cap is silently dropped) or the row exceeded a declared column size. The FIRST such failure per table emits a one-time advisory (the failure would otherwise be silent — see the scaling-limits doc); the return value is unchanged.
mapType()  : int
Translate Store::TYPE_* constants (which alias OpenSwoole\Table::TYPE_* — see the facade constant declarations in Store.php) so the schema map stays backend-neutral. Existing code passing Table::TYPE_* directly still works because the numeric values are identical.
warnCapacity()  : void
Surface the otherwise-silent set() failure ONCE per table per worker.

Properties

$capacityWarned

private array<string, true> $capacityWarned = []

Tables a capacity warning has already been emitted for (rate-limit to once per table per worker).

$maxRows

private array<string, int> $maxRows = []

Declared maxRows per table — for the silent-full advisory.

$schemas

private array<string, array<string, array{0: int, 1?: int}>> $schemas = []

Methods

clear()

Delete all rows from the named table by iterating and deleting each key individually (no native bulk-delete on OpenSwoole\Table).

public clear(string $name) : void

No-op when the table doesn't exist.

Parameters
$name : string

count()

Return the number of rows in the named table, or 0 when the table doesn't exist.

public count(string $name) : int
Parameters
$name : string
Return values
int

decr()

Atomically decrement column $col by $by. Returns the new column value (int/float per the column type), or 0 when the table doesn't exist.

public decr(string $name, string $key, string $col[, int|float $by = 1 ]) : int|float
Parameters
$name : string
$key : string
$col : string
$by : int|float = 1
Return values
int|float

del()

Delete a row by key. Returns false when the table doesn't exist or the key was already absent.

public del(string $name, string $key) : bool
Parameters
$name : string
$key : string
Return values
bool

exists()

Return true when the named table contains a row with the given key.

public exists(string $name, string $key) : bool
Parameters
$name : string
$key : string
Return values
bool

get()

Read a row or a single field from the named table. Returns null when the table or key doesn't exist. When $field is provided, returns the field's scalar value or null if absent.

public get(string $name, string $key[, string|null $field = null ]) : mixed
Parameters
$name : string
$key : string
$field : string|null = null

incr()

Atomically increment column $col by $by. Returns the new column value — int for an INT column, float for a FLOAT column (OpenSwoole\Table supports both) — or 0 when the table doesn't exist. Matches the StoreBackend::incr(): int|float contract. $by is passed through unchanged so a FLOAT column increments by a fractional amount (#420 — the old (int) $by cast truncated the step AND the narrow : int return type fatally rejected the float a FLOAT column returns).

public incr(string $name, string $key, string $col[, int|float $by = 1 ]) : int|float
Parameters
$name : string
$key : string
$col : string
$by : int|float = 1
Return values
int|float

iterate()

Iterate all rows in the named table as a Generator. Yields string keys mapped to array<string, scalar> row arrays. Returns immediately when the table doesn't exist.

public iterate(string $name) : Generator<string, array<string, scalar>>
Parameters
$name : string
Return values
Generator<string, array<string, scalar>>

iteratePaged()

Paginated iteration. **O(N²/page) on the Table backend** — the cursor is a skip-offset and each call re-iterates from row 0, discarding $cursor rows before collecting the next $count. Paginating all N rows therefore costs O(N² / page). Fine for a few thousand rows; for large tables use the Redis/Tiered backend (true SCAN cursor) instead, or iterate() if you can hold one pass in memory. See the scaling-limits doc.

public iteratePaged(string $name[, string $cursor = '0' ][, int $count = 100 ]) : array{cursor: string, rows: array>}
Parameters
$name : string
$cursor : string = '0'
$count : int = 100
Return values
array{cursor: string, rows: array>}

make()

Create a named OpenSwoole\Table with the given schema. Each column in $columns is [TYPE_*, $size]. When $columns is empty, a single 'value' column of type TYPE_STRING(256) is created. $opts is accepted for interface compatibility but unused by this backend.

public make(string $name, int $maxRows, array<string|int, mixed> $columns[, array<string|int, mixed> $opts = [] ]) : void
Parameters
$name : string
$maxRows : int
$columns : array<string|int, mixed>
$opts : array<string|int, mixed> = []

backend-specific: mode/ttl/etc.

mget()

Bulk read multiple rows. Missing keys are returned as null in the result map. Non-scalar column values are silently skipped (they cannot arise from a normal set() call on this backend).

public mget(string $name, array<string|int, mixed> $keys) : array<string, array<string, scalar>|null>
Parameters
$name : string
$keys : array<string|int, mixed>
Return values
array<string, array<string, scalar>|null>

mset()

Bulk write multiple rows by calling set() for each entry in sequence.

public mset(string $name, array<string|int, mixed> $rows) : bool

Returns true when all writes succeeded; false when any single write failed (the rest still proceed — no rollback).

Parameters
$name : string
$rows : array<string|int, mixed>
Return values
bool

names()

Return the names of all tables registered via make().

public names() : array<int, string>
Return values
array<int, string>

rawTable()

Direct access to the underlying Table — used by the Store facade to keep Store::table($name) working under the table backend.

public rawTable(string $name) : Table|null
Parameters
$name : string
Return values
Table|null

schema()

Column schema as registered via make(). Exposed for tests + the future tiered backend; mirrors what RedisBackend stores internally for TypeCodec decoding.

public schema(string $name) : array<string, array{0: int, 1?: int}>|null
Parameters
$name : string
Return values
array<string, array{0: int, 1?: int}>|null

set()

Write a row to the named table. Returns false when the table doesn't exist or when OpenSwoole\Table::set() fails — most commonly because the table is **full** (maxRows is a HARD boot-time cap with NO eviction, so every new distinct key past the cap is silently dropped) or the row exceeded a declared column size. The FIRST such failure per table emits a one-time advisory (the failure would otherwise be silent — see the scaling-limits doc); the return value is unchanged.

public set(string $name, string $key, array<string|int, mixed> $row) : bool
Parameters
$name : string
$key : string
$row : array<string|int, mixed>

Column-name → value map. All declared columns must be present.

Return values
bool

mapType()

Translate Store::TYPE_* constants (which alias OpenSwoole\Table::TYPE_* — see the facade constant declarations in Store.php) so the schema map stays backend-neutral. Existing code passing Table::TYPE_* directly still works because the numeric values are identical.

private mapType(int $type) : int
Parameters
$type : int
Return values
int

warnCapacity()

Surface the otherwise-silent set() failure ONCE per table per worker.

private warnCapacity(string $name, Table $t, string $key) : void

Distinguishes "table full" (count at the hard maxRows cap, no eviction) from "row didn't fit" (a column value exceeded its declared size).

Parameters
$name : string
$t : Table
$key : string
On this page