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

utils.php

Table of Contents

Constants

SID  : mixed = ''

Functions

php_session_encode_from_array()  : string
Encode an array into PHP's native php session serialize format (key|serialized_value for each key). Matches the format produced by session.serialize_handler = php (the default in mod_php / phpredis).
php_session_decode_to_array()  : array<string, mixed>
Decode a PHP session string back to an associative array.
zeal_session_opened_handler()  : SessionHandlerInterface|null
Resolve the active custom session handler, guaranteeing the SessionHandlerInterface contract that open() precedes any read()/write()/destroy() (#369). A freshly-resolved handler — session_regenerate_id() / session_write_close() reached without a prior session_start() in this request — was used un-open()ed, and FileSessionHandler's typed $savePath fataled on first write() (breaking the textbook login fixation defence with an uncaught Error).
zeal_session_start()  : bool
zeal_valid_session_id()  : bool
Whether a session id is safe to use in a filesystem path / store key.
zeal_session_strict_should_regenerate()  : bool
session.use_strict_mode provenance decision (#244).
zeal_session_set_save_handler()  : bool
Coroutine-mode override of session_set_save_handler() (#295).
zeal_session_id()  : string|false
Get or set the session ID.
zeal_session_status()  : int
Return the current session status (PHP_SESSION_ACTIVE or PHP_SESSION_NONE).
zeal_session_name()  : string
Get or set the session name (the cookie name, e.g. 'PHPSESSID').
zeal_session_write_close()  : bool
Write session data to the backing store and mark the session inactive.
zeal_session_destroy()  : bool
Destroy the session and delete its backing storage.
zeal_session_unset()  : void
Unset all session variables without destroying the session.
zeal_session_regenerate_id()  : bool
Regenerate the session ID, optionally deleting the old session.
zeal_session_get_cookie_params()  : array{lifetime: int, path: string, domain: string, secure: bool, httponly: bool, samesite?: string}
Get the current session cookie parameters.
zeal_session_set_cookie_params()  : void
Set session cookie parameters.
zeal_session_cache_limiter()  : string
Get or set the session cache limiter (e.g. 'nocache', 'public', 'private').
zeal_session_commit()  : bool
Alias for zeal_session_write_close() — write session data and close.
zeal_session_cache_expire()  : int
Get or set the session cache expiry in minutes.
zeal_session_abort()  : bool
Discard in-memory session changes and reload session data from the file.
zeal_session_encode()  : string
Encode the current session data to PHP's php serialize format string.
zeal_session_decode()  : bool
Decode a session data string and populate the active session.
zeal_session_create_id()  : string|false
Create a new session ID, optionally with a $prefix.
zeal_session_save_path()  : string
Get or set the session save path.
zeal_session_module_name()  : string
Get or set the session module name (e.g. 'files', 'redis').
zeal_session_gc()  : int
Garbage-collect expired sessions for the active storage.

Constants

Functions

php_session_encode_from_array()

Encode an array into PHP's native php session serialize format (key|serialized_value for each key). Matches the format produced by session.serialize_handler = php (the default in mod_php / phpredis).

php_session_encode_from_array(array<string, mixed> $data) : string
Parameters
$data : array<string, mixed>
Return values
string

php_session_decode_to_array()

Decode a PHP session string back to an associative array.

php_session_decode_to_array(string $data) : array<string, mixed>

Tries unserialize() first (handles the php_serialize handler format), then falls back to parsing the native php format (key|serialized_value pairs). All unserialize() calls use ['allowed_classes' => ['stdClass']] — see the file-level security note above.

Parameters
$data : string
Return values
array<string, mixed>

zeal_session_opened_handler()

Resolve the active custom session handler, guaranteeing the SessionHandlerInterface contract that open() precedes any read()/write()/destroy() (#369). A freshly-resolved handler — session_regenerate_id() / session_write_close() reached without a prior session_start() in this request — was used un-open()ed, and FileSessionHandler's typed $savePath fataled on first write() (breaking the textbook login fixation defence with an uncaught Error).

zeal_session_opened_handler() : SessionHandlerInterface|null

open() is invoked once per request (flagged in session_params).

Return values
SessionHandlerInterface|null

zeal_session_start()

zeal_session_start() : bool
Return values
bool

zeal_valid_session_id()

Whether a session id is safe to use in a filesystem path / store key.

zeal_valid_session_id(string $id) : bool

Rejects the inputs that would let an attacker-chosen PHPSESSID escape the session save directory: empty/oversized values, NUL bytes, path separators (/, \), and parent-directory references (..). The character set is otherwise left permissive so a legitimate custom/legacy session id is not rejected — the basename() applied at every sess_<id> file sink is the belt-and-suspenders traversal guard.

Parameters
$id : string
Return values
bool

zeal_session_strict_should_regenerate()

session.use_strict_mode provenance decision (#244).

zeal_session_strict_should_regenerate(bool $strictMode, bool $clientSupplied, array<string|int, mixed> $loadedSession[, bool|null $storeEntryExists = null ]) : bool

zeal_valid_session_id() checks only the FORMAT of a client-supplied id; a well-formed but server-never-issued id (a planted/fixated PHPSESSID) still passes it. PHP's session.use_strict_mode=1 rejects any id the server has no record of by minting a fresh one. The session managers reproduce that here: after zeal_session_start() has loaded the store for a CLIENT-SUPPLIED id, an EMPTY result means the id is unrecognised (stale / foreign / never issued) — so it must not be honoured, and a fresh server-generated id is issued in its place. This is the single trust check both CoSessionManager and SessionManager consult, kept here so it is unit-testable without driving a full request through OpenSwoole.

PHP's session.use_strict_mode rejects ids the server NEVER ISSUED. When the caller can tell whether the id had a BACKING STORE ENTRY (file existed / handler returned data), that is the canonical signal (ext-zealphp#2): an issued-but-still-empty session — the cookie sent on a data-less first visit, a redirect, any page that stores nothing — is a KNOWN id and must NOT rotate. The old data-emptiness heuristic rotated those on EVERY request, which (combined with the regenerate→write_close sid desync, fixed alongside) cascaded into rotate-and-lose-every-write. The array heuristic remains the fallback for callers that cannot determine store existence.

Parameters
$strictMode : bool

App::$session_strict_mode.

$clientSupplied : bool

Whether the active id came from the client (cookie/query param) rather than being server-minted.

$loadedSession : array<string|int, mixed>

The session data the store resolved for that id; its emptiness is the FALLBACK signal when $storeEntryExists is unknown.

$storeEntryExists : bool|null = null

Whether the id had a backing store entry at load time ($g->session_params ['session_existed']); null = unknown.

Return values
bool

true when the id must be rotated to a fresh server id.

zeal_session_set_save_handler()

Coroutine-mode override of session_set_save_handler() (#295).

zeal_session_set_save_handler([mixed $handler = null ][, bool $register_shutdown = true ]) : bool

Native session_set_save_handler() registers with PHP's session module, which the zeal_session_* overrides never consult — so a custom handler (Redis, etc.) was silently ignored and sessions fell back to the inline file path. This routes the handler to the slots the framework actually reads, in BOTH scopes:

  • App::$session_handler (process-wide) so every future request and worker sees it — the common boot-time call shape; and
  • the current coroutine's $g->session_params['handler'] (immediate) so a per-request middleware call takes effect for THIS request.

Only the object-handler form is supported (PHP's modern signature). The legacy 6-callable form and a non-handler argument are rejected (return false), as the zeal_session_* core requires a \SessionHandlerInterface.

Parameters
$handler : mixed = null

A \SessionHandlerInterface instance.

$register_shutdown : bool = true

Accepted for signature parity; unused (the managers own the write-close lifecycle).

Return values
bool

true when wired, false for an unsupported argument.

zeal_session_id()

Get or set the session ID.

zeal_session_id([string|null $id = null ]) : string|false

With no argument: reads the PHPSESSID (or custom session name) cookie from $g->cookie. When no cookie is present a fresh ID is generated via session_create_id() and stashed in $g->cookie. A malformed inbound ID (path traversal, NUL, oversized) is silently replaced with a fresh one.

NOTE: this function only validates id FORMAT. The session.use_strict_mode PROVENANCE check (rotating a well-formed but never-issued id that loads an empty session — #244) lives in the session managers, which call zeal_session_strict_should_regenerate() after the store has been read.

Parameters
$id : string|null = null

Pass a string to set the session ID explicitly.

Return values
string|false

The current (or newly-set) session ID.

zeal_session_status()

Return the current session status (PHP_SESSION_ACTIVE or PHP_SESSION_NONE).

zeal_session_status() : int

Mode-aware: in superglobals mode inspects $GLOBALS['_SESSION']; in coroutine mode checks whether the typed $g->session slot is initialised (it is unset() by zeal_session_write_close() / zeal_session_destroy() to mark a session inactive).

Return values
int

zeal_session_name()

Get or set the session name (the cookie name, e.g. 'PHPSESSID').

zeal_session_name([string|null $name = null ]) : string

Stored per-request in $g->session_params['name'].

Parameters
$name : string|null = null

Pass null to read the current value.

Return values
string

The current (or newly-set) session name.

zeal_session_write_close()

Write session data to the backing store and mark the session inactive.

zeal_session_write_close() : bool

Coroutine-safe replacement for PHP's session_write_close(). Performs a read-merge-write under flock(LOCK_EX) (file backend) or an optimistic WATCH/MULTI/EXEC retry loop (custom \SessionHandlerInterface) to guard against concurrent-coroutine last-write-wins data loss on the same session ID. The merge is shallow — top-level keys added by a concurrent request survive, but conflicting nested arrays are last-write-wins.

After writing, $g->session (coroutine mode) or $GLOBALS['_SESSION'] (superglobals mode) is unset() so zeal_session_status() returns PHP_SESSION_NONE for the remainder of the request.

Return values
bool

zeal_session_destroy()

Destroy the session and delete its backing storage.

zeal_session_destroy() : bool

Deletes the session file (or calls \SessionHandlerInterface::destroy() for custom backends), removes $g->session and $_SESSION, and clears the session cookie from $g->cookie. Sets $g->_session_started to false.

Return values
bool

zeal_session_unset()

Unset all session variables without destroying the session.

zeal_session_unset() : void

Resets $g->session to [] and, in superglobals mode, also clears $GLOBALS['_SESSION']. The session file / backend entry is NOT deleted — call zeal_session_destroy() to remove it entirely.

zeal_session_regenerate_id()

Regenerate the session ID, optionally deleting the old session.

zeal_session_regenerate_id([bool $delete_old_session = false ]) : bool

Coroutine-safe replacement for PHP's session_regenerate_id(). Copies the current in-memory session data to the new ID via the active backend (custom \SessionHandlerInterface or file), then emits a fresh Set-Cookie header so the client switches to the new ID. Gated by App::$session_lifecycle and session.use_cookies — same guards as zeal_session_start().

Parameters
$delete_old_session : bool = false

When true, the old session file/entry is deleted.

Return values
bool

Get the current session cookie parameters.

zeal_session_get_cookie_params() : array{lifetime: int, path: string, domain: string, secure: bool, httponly: bool, samesite?: string}

Returns the array stored in $g->session_params['cookie_params'], falling back to safe defaults (path='/', httponly=true, samesite='Lax').

Return values
array{lifetime: int, path: string, domain: string, secure: bool, httponly: bool, samesite?: string}

Set session cookie parameters.

zeal_session_set_cookie_params(int|array<string, mixed> $lifetime_or_options[, string $path = null ][, string $domain = null ][, bool $secure = null ][, bool $httponly = null ]) : void

Accepts either the positional-args form (PHP < 8.0 style) or an options array (PHP 8.0+ session_set_cookie_params(array $options) style). Both are merged over the defaults ['lifetime'=>0, 'path'=>'/', 'domain'=>'', 'secure'=>false, 'httponly'=>false, 'samesite'=>'Lax'].

Parameters
$lifetime_or_options : int|array<string, mixed>

Integer lifetime in seconds, or an options array.

$path : string = null
$domain : string = null
$secure : bool = null
$httponly : bool = null

zeal_session_cache_limiter()

Get or set the session cache limiter (e.g. 'nocache', 'public', 'private').

zeal_session_cache_limiter([string|null $cache_limiter = null ]) : string

Stored per-request in $g->cache_limiter. Defaults to 'nocache'.

Parameters
$cache_limiter : string|null = null

Pass null to read the current value.

Return values
string

zeal_session_commit()

Alias for zeal_session_write_close() — write session data and close.

zeal_session_commit() : bool

Mirrors PHP's session_commit(), which is itself an alias of session_write_close().

Return values
bool

zeal_session_cache_expire()

Get or set the session cache expiry in minutes.

zeal_session_cache_expire([int|null $cache_expire = null ]) : int

Stored per-request in $g->cache_expire. Defaults to 180 when not set.

Parameters
$cache_expire : int|null = null

Pass null to read the current value.

Return values
int

zeal_session_abort()

Discard in-memory session changes and reload session data from the file.

zeal_session_abort() : bool

Mirrors PHP's session_abort(): any writes to $g->session or $_SESSION since the last session_start() are thrown away, and the session data is re-read from the session file on disk. Returns true always.

Return values
bool

zeal_session_encode()

Encode the current session data to PHP's php serialize format string.

zeal_session_encode() : string

Reads from $GLOBALS['_SESSION'] in superglobals mode, or from RequestContext::instance()->session in coroutine mode.

Return values
string

zeal_session_decode()

Decode a session data string and populate the active session.

zeal_session_decode(string $data) : bool

Mirrors PHP's session_decode(): parses $data via php_session_decode_to_array() and stores the result in both $g->session and $GLOBALS['_SESSION'] (in superglobals mode). Returns false when $data is empty or decodes to an empty array.

Parameters
$data : string
Return values
bool

zeal_session_create_id()

Create a new session ID, optionally with a $prefix.

zeal_session_create_id([string $prefix = '' ]) : string|false

Thin wrapper around PHP's session_create_id().

Parameters
$prefix : string = ''

Optional prefix prepended to the generated ID.

Return values
string|false

The new session ID, or false on failure.

zeal_session_save_path()

Get or set the session save path.

zeal_session_save_path([string|null $path = null ]) : string

Stored per-request in $g->session_params['save_path']. Defaults to '/var/lib/php/sessions' when not set.

Parameters
$path : string|null = null

Pass null to read the current value.

Return values
string

The current (or newly-set) save path.

zeal_session_module_name()

Get or set the session module name (e.g. 'files', 'redis').

zeal_session_module_name([string|null $module = null ]) : string

Stored per-request in $g->session_module_name. Defaults to 'files' when not set. This is a ZealPHP-internal tracking field; the actual backend is determined by the registered \SessionHandlerInterface.

Parameters
$module : string|null = null

Pass null to read the current value.

Return values
string

zeal_session_gc()

Garbage-collect expired sessions for the active storage.

zeal_session_gc(int $maxlifetime) : int

ZealPHP replaced PHP's probabilistic per-request GC (session.gc_probability) with deterministic, explicit collection — but nothing called it, so on a long-lived worker sess_* files (default storage) accumulated until inodes exhausted, and a leaked/abandoned PHPSESSID stayed replayable forever. App::run() now schedules this on a worker-0 timer (see App::registerSessionGc()).

A registered SessionHandlerInterface owns its own GC (Redis/Table handlers already expire rows server-side); the default inline file path sweeps sess_* files whose mtime is older than $maxlifetime seconds.

Parameters
$maxlifetime : int

Seconds of inactivity after which a session expires.

Return values
int

Number of file entries removed (handler backends return their own count, or 0).

On this page