Skip to main content

Caching ("freeze the dough")

React's cache() dedupes data fetching within a single render: if ten different server components each ask for the same user by id, the wrapped function runs once and every caller gets back the same result, instead of issuing ten identical queries.

PHP has no persistent render tree to hang that lifetime off of, so the closest equivalent is per-request memoization: a store that lives for the duration of the request (the process, in the simple php -S case) and is keyed by the function plus its arguments.

use function Attitude\PHPX\Server\cache;

$getUser = cache(fn (string $id) => $db->user($id)); // loads once per id per request

$getUser('42'); // runs the query
$getUser('42'); // returns the stored result, no query
$getUser('43'); // different args, runs again

Why this fits the "dough" framing

The door and tuples doc frames a PHPX tuple as inspectable, serializable dough — data you can var_dump(), json_encode(), or diff before anything renders. cache() leans on the same property: the key is built by serializing the function's identity and its arguments, so a cached call is really just "the same dough, already mixed" — recognized by its ingredients (arguments), not recomputed.

That's also the honest limit: only serializable arguments are memoized. A call with a closure, a database connection, or another live object as an argument can't be turned into a stable key, so it's never cached — it always falls through to the wrapped function. This is the same "door" rule that governs Client() props and server action arguments; cache() just applies it to memoization keys instead of a wire format.

Clearing the store

In a long-lived process — a queue worker, a persistent PHP server — the cache store outlives a single request unless you clear it yourself. Call Cache::clear() at the start or end of each request boundary:

use Attitude\PHPX\Server\Cache;

Cache::clear(); // reset before handling the next request