Cache
File-based cache for expensive reads such as DB queries or config snapshots. Only the file driver is supported.
Use this for data that is slow to build and shared between requests. For per-visitor state use Storage sessions instead.
Setup
Pick a writable directory once, before the first cache call.
<?php
define('ROOLITH_CACHE_DIR', APP_ROOT . '/cache');
require APP_ROOT . '/vendor/autoload.php';The directory is created automatically. Without this, cache falls back to the system temp dir.
To override per call instead:
use Roolith\Caching\Cache\CacheFactory;
CacheFactory::driver('file', ['dir' => APP_ROOT . '/cache']);Basic usage
Always pass TTL in seconds. get() returns false on miss or expiry, so check has() first.
<?php
use Roolith\Caching\Cache\CacheFactory;
CacheFactory::put('user_1', $user, 3600); // save for 1 hour
$exists = CacheFactory::has('user_1'); // bool
$user = CacheFactory::get('user_1'); // value, or false on miss / expiry
CacheFactory::remove('user_1'); // delete one key
CacheFactory::flush(); // delete everythingCommon TTLs: 60 for a minute, 3600 for an hour.
Remember pattern
Check the cache, fall back to the loader, then store. Give each query its own key so entries never collide, and delete the key when the source data changes.
<?php
use Roolith\Caching\Cache\CacheFactory;
function activeUsers(callable $loader): mixed
{
if (CacheFactory::has('users:active')) {
$cached = CacheFactory::get('users:active');
if ($cached !== false) {
return $cached;
}
}
$fresh = $loader();
CacheFactory::put('users:active', $fresh, 3600);
return $fresh;
}
$users = activeUsers(fn () => $db->query('SELECT * FROM users'));
CacheFactory::remove('users:active'); // invalidate when users changeOther ways to use it
Use Cache directly when you want an instance instead of statics.
<?php
use Roolith\Caching\Cache\Cache;
$cache = new Cache();
$cache->driver('file', ['dir' => APP_ROOT . '/cache']);
$cache->put('foo', 'bar', 3600);
echo $cache->get('foo');Use PSR-6 or PSR-16 only when a library requires that interface.
<?php
use Roolith\Caching\Cache\Pool;
use Roolith\Caching\Cache\SimpleCache;
use Roolith\Caching\Driver\FileDriver;
$driver = new FileDriver(['dir' => APP_ROOT . '/cache']);
// PSR-6
$pool = new Pool($driver);
$item = $pool->getItem('foo');
if (!$item->isHit()) {
$item->set([1, 2, 3])->expiresAfter(3600);
$pool->save($item);
}
// PSR-16
$simple = new SimpleCache($driver);
$simple->set('foo', 'bar', 3600);
echo $simple->get('foo');Worked example
Copy-paste read-through helpers for expensive, rarely-changing reads - slow queries or config snapshots - never by default on every request.
<?php
use Roolith\Caching\Cache\CacheFactory;
function cachedModelQuery(string $key, callable $loader, int $ttl = 3600): mixed
{
if (CacheFactory::has($key)) {
$cached = CacheFactory::get($key);
if ($cached !== false) {
return $cached;
}
}
$fresh = $loader();
CacheFactory::put($key, $fresh, $ttl);
return $fresh;
}
function cachedConfig(string $key, callable $loader, int $ttl = 3600): mixed
{
if (CacheFactory::has($key)) {
$cached = CacheFactory::get($key);
if ($cached !== false) {
return $cached;
}
}
$fresh = $loader();
CacheFactory::put($key, $fresh, $ttl);
return $fresh;
}
// Each query needs its own key so entries never collide.
$users = cachedModelQuery('users:active', fn () => $db->query('SELECT * FROM users'));
$settings = cachedConfig('config:snapshot', fn () => require APP_ROOT . '/config/config.php');
// Flush when the source changes.
CacheFactory::remove('users:active');Always check has() before trusting get() because get() returns false on miss, expiry, or corrupt entries.