Caching

True\Cache is a small SQLite-backed key/value cache. Use it to memoize an expensive page render, stash a third-party API response, or hold any chunk of data you don't want to recompute on every request.

Setup

The cache wants a Truecast\Hopper SQLite connection. A starter database ships at vendor/truecastdesign/true/data/caching.sqlite — copy it into app/data/ first so it isn't blown away by a composer update:

$DBCache = new Truecast\Hopper([
    'driver'   => 'sqlite',
    'database' => BP.'/app/data/caching.sqlite',
]);

$App->cache = new True\Cache($DBCache);

Cache a page render

The canonical use case: cache the rendered HTML of a slow page keyed by URL. Buffer the output, store it on miss, return the cached copy on hit:

$url = strtok($_SERVER["REQUEST_URI"], '?'); // strip the query string

$cached = $App->cache->get($url);

if ($cached === false) {
    ob_start();
    // ... expensive render
    $buffer = ob_get_contents();
    ob_end_flush();
    $App->cache->set($url, $buffer);
} else {
    echo $cached;
}

Cache arbitrary data

Arrays and objects are stored as JSON, so you can keep structured payloads — handy when the rendered page depends on a few derived values (title, description, etc.):

$cached = $App->cache->get($url);

if ($cached === false) {
    ob_start();
    // ... expensive render
    $buffer = ob_get_contents();
    ob_end_flush();

    $payload = (object) [
        'buffer'      => $buffer,
        'docTitle'    => $docTitle,
        'description' => $description,
    ];
    $App->cache->set($url, $payload);
} else {
    $buffer      = $cached->buffer;
    $docTitle    = $cached->docTitle;
    $description = $cached->description;
}

API

MethodPurpose
set($key, $content): boolStore a value (string, int, bool, array, or object).
get($key): mixedReturn the stored value, or false if the key is missing.
delete($key): boolRemove a single key or an array of keys.
flush(): boolEmpty the entire cache.
getStats(): objectReturns an object with bytes (total size) and records (entry count).
$App->cache->delete(['page1', 'page2']);   // bulk delete

$stats = $App->cache->getStats();
echo "Cache size: {$stats->bytes} bytes, {$stats->records} records";

Tips

  • Use meaningful keys to avoid collisions across pages — the URL is fine, but namespace API-response keys (e.g. "geo:" . $ip) so they don't clash.
  • Flush after deploys that change the rendered output, or build a key suffix that includes a deploy revision.
  • The cache has no built-in TTL — call delete() from a scheduled task if you want time-based eviction.