On this page
FileCache and ScopedCache
When your code needs a cache (compiled artifacts, parsed data, or a build pipeline), use
Gacela\Framework\Cache\FileCache. It is the value layer of Gacela's caching: the framework does not
put anything in it on its own; your application decides the keys, the values, and the lifetimes.
FileCache
use Gacela\Framework\Cache\FileCache;
$cache = new FileCache('/var/cache/myapp');
$cache->put('user:42', $user, ttl: 600);
$cache->get('user:42'); // $user, or null after TTL expiry
$cache->forget('user:42');
$cache->clear();- One
.phpfile per key (SHA1-hashed), written atomically via staged.tmp+rename. writeContentsAtomically(string $file, string $content): bool— atomically writes already-rendered content to a path, with the same staged-.tmp+renameguarantees asput(). The higher-levelwriteAtomically()wraps it.- TTL per entry;
ttl: 0means forever, a negative TTL writes an already-expired entry.InMemoryCacheStoragefollows the same rule as of 2.1. See the TTL contract. beginBatch()/commitBatch()defer writes behind a single index-locked flush. Useful for warming many entries at once.stats()returns entry count, total bytes, and oldest/newest timestamps.- Safe against torn reads: concurrent readers see either the previous file or the new one, never a half-written one.
ScopedCache: dependency-aware decorator
When invalidating one entry should cascade to every downstream entry that derived from it, wrap FileCache in
ScopedCache:
use Gacela\Framework\Cache\FileCache;
use Gacela\Framework\Cache\ScopedCache;
$cache = new ScopedCache(new FileCache('/var/cache/myapp'));
$cache->put('ns:core', $envCore);
$cache->put('file:a.php', $compiledA);
$cache->put('fragment:a#1', $fragment);
$cache->dependsOn('file:a.php', 'ns:core');
$cache->dependsOn('fragment:a#1', 'file:a.php');
$cache->invalidate('ns:core'); // cascades: file:a.php and fragment:a#1 also go
$cache->invalidateLeaf('file:a.php'); // only this key; dependents stay validget/put/hasdelegate straight to the underlyingFileCache. Zero overhead on the hot path.- The dependency graph is persisted alongside the values (
.gacela-scoped-cache-graph.php) and survives process restarts. - Cycles are rejected eagerly at
dependsOn(): self, two-node, and transitive. - Single-writer concurrency: multiple processes racing on
dependsOn()may lose edges added between load and persist.
See also
- Caching: the three caching layers and how to pick one
- Cacheable methods: caching Facade method results instead of raw values