Skip to content
Ray Fung edited this page Feb 26, 2026 · 3 revisions

Cache System

Razy provides a PSR-16 compatible caching layer with a static facade, pluggable storage adapters, and file-validation support. The Cache system supports File, Redis, APCu, and Null adapters out of the box.


Table of Contents


Quick Start

use Razy\Cache;

use Razy\Cache\FileAdapter;



// Initialize with file adapter

Cache::initialize('/path/to/cache', new FileAdapter('/path/to/cache'));



// Store and retrieve values

Cache::set('user.profile.123', $userData, ttl: 3600);

$profile = Cache::get('user.profile.123');



// Check existence

if (Cache::has('user.profile.123')) {

    // cached

}



// Delete

Cache::delete('user.profile.123');

Initialization

The Cache facade must be initialized before use. If not initialized, it auto-initializes with a NullAdapter (no-op):

use Razy\Cache;

use Razy\Cache\FileAdapter;

use Razy\Cache\RedisAdapter;



// File-based cache

Cache::initialize('/var/cache/razy', new FileAdapter('/var/cache/razy'));



// Redis-based cache

$redis = new Redis();

$redis->connect('127.0.0.1', 6379);

Cache::initialize('', new RedisAdapter($redis, 'myapp_'));



// Check status

Cache::isInitialized(); // true



// Enable/disable at runtime (disabled = NullAdapter behavior)

Cache::setEnabled(false);

Cache::isEnabled(); // false



// Swap adapter at runtime

Cache::setAdapter(new RedisAdapter($redis));



// Get current adapter

$adapter = Cache::getAdapter();

Basic Operations

All operations follow the PSR-16 SimpleCacheInterface contract:

use Razy\Cache;



// SET → store a value with optional TTL

Cache::set('key', 'value');                    // no expiry

Cache::set('key', 'value', 3600);              // expires in 1 hour (seconds)

Cache::set('key', 'value', new DateInterval('PT1H')); // DateInterval TTL



// GET → retrieve with optional default

$value = Cache::get('key');                    // returns null if missing

$value = Cache::get('key', 'fallback');        // returns 'fallback' if missing



// HAS → check existence

if (Cache::has('key')) {

    // ...

}



// DELETE → remove a single entry

Cache::delete('key');



// CLEAR → remove all entries

Cache::clear();

Batch Operations

Efficiently read/write multiple keys in a single call:

// SET multiple values

Cache::setMultiple([

    'user.1' => $user1,

    'user.2' => $user2,

    'user.3' => $user3,

], ttl: 3600);



// GET multiple values

$users = Cache::getMultiple(['user.1', 'user.2', 'user.3']);

// Returns: ['user.1' => $user1, 'user.2' => $user2, 'user.3' => $user3]



// GET with default for missing keys

$users = Cache::getMultiple(['user.1', 'user.999'], default: null);

// Returns: ['user.1' => $user1, 'user.999' => null]



// DELETE multiple

Cache::deleteMultiple(['user.1', 'user.2']);

File-Validated Cache

A unique Razy feature that ties cached data to a source file's modification time. If the file changes, the cache is automatically invalidated:

// Cache compiled template → auto-invalidates when template.html changes

Cache::setValidated(

    key: 'template.compiled.main',

    filePath: '/path/to/template.html',

    data: $compiledTemplate,

    ttl: 86400

);



// Retrieve → returns null if file has been modified since caching

$compiled = Cache::getValidated(

    key: 'template.compiled.main',

    filePath: '/path/to/template.html'

);



if ($compiled === null) {

    // File changed or cache expired → recompile

    $compiled = compileTemplate('/path/to/template.html');

    Cache::setValidated('template.compiled.main', '/path/to/template.html', $compiled);

}

How it works: setValidated() stores the file's mtime alongside the cached data. getValidated() compares the stored mtime with the current file's mtime → if they differ, the cache entry is considered stale and returns $default.


Adapters

FileAdapter

Directory-sharded file cache with atomic writes. Files are stored as {dir}/{xx}/{md5}.cache:

use Razy\Cache\FileAdapter;



$adapter = new FileAdapter('/var/cache/razy');



// All PSR-16 methods available

$adapter->set('key', 'value', 3600);

$value = $adapter->get('key');



// File-specific extras

$stats = $adapter->getStats();

// Returns: ['directory' => '/var/cache/razy', 'files' => 142, 'size' => 1048576]



// Garbage collection → removes expired entries, returns count removed

$removed = $adapter->gc();

Features:

  • Atomic writes via temp file + rename (crash-safe)

  • Two-character directory sharding (e.g. ab/abcdef123456.cache)

  • Lazy purge on read (expired entries deleted when accessed)

  • Windows-compatible file handling

  • Key validation rejects PSR-16 reserved characters: {}()/\@:

RedisAdapter

High-performance Redis-backed cache:

use Razy\Cache\RedisAdapter;



$redis = new Redis();

$redis->connect('127.0.0.1', 6379);

$redis->auth('password');

$redis->select(2);



$adapter = new RedisAdapter($redis, prefix: 'myapp_');



// Access underlying Redis instance

$redis = $adapter->getRedis();

Features:

  • Configurable key prefix (default: 'razy_')

  • serialize/unserialize for complex PHP values

  • Batch getMultiple uses Redis MGET for efficiency

  • clear() with prefix uses SCAN to delete only prefixed keys (safe for shared Redis)

ApcuAdapter

Shared memory cache via APCu extension:

use Razy\Cache\ApcuAdapter;



// Requires ext-apcu

$adapter = new ApcuAdapter(prefix: 'myapp_');

Features:

  • High performance (shared memory, no I/O)

  • clear() uses APCuIterator with prefix regex to only clear own entries

  • Best for single-server deployments

NullAdapter

No-op adapter for testing or disabled cache mode:

use Razy\Cache\NullAdapter;



$adapter = new NullAdapter();

$adapter->get('key');     // always returns default

$adapter->set('key', 1);  // always returns true

$adapter->has('key');      // always returns false

Graceful Degradation

All Cache facade operations wrap adapter calls in try/catch(\Throwable). If an adapter throws (e.g. Redis connection lost), the operation fails silently and returns the default/false:

// Even if Redis is down, this won't crash your application

$value = Cache::get('key', 'fallback'); // returns 'fallback'

Cache::set('key', 'value');             // returns false

When the cache is disabled via Cache::setEnabled(false), all operations behave as if using the NullAdapter.


API Reference

Cache Facade (Static)

| Method | Signature | Description |

| --- | --- | --- |

| initialize | (string $cacheDir, ?CacheInterface $adapter): void | Set up cache system |

| isInitialized | (): bool | Check if initialized |

| setEnabled | (bool $enabled): void | Enable/disable caching |

| isEnabled | (): bool | Check if enabled |

| getAdapter | (): CacheInterface | Get current adapter |

| setAdapter | (CacheInterface $adapter): void | Swap adapter |

| get | (string $key, mixed $default = null): mixed | Retrieve value |

| set | (string $key, mixed $value, int\|DateInterval\|null $ttl = null): bool | Store value |

| delete | (string $key): bool | Remove entry |

| clear | (): bool | Remove all entries |

| has | (string $key): bool | Check existence |

| getMultiple | (iterable $keys, mixed $default = null): iterable | Batch retrieve |

| setMultiple | (iterable $values, int\|DateInterval\|null $ttl = null): bool | Batch store |

| deleteMultiple | (iterable $keys): bool | Batch remove |

| getValidated | (string $key, string $filePath, mixed $default = null): mixed | File-validated get |

| setValidated | (string $key, string $filePath, mixed $data, int\|DateInterval\|null $ttl = null): bool | File-validated set |

| reset | (): void | Reset facade state |

FileAdapter Extras

| Method | Signature | Description |

| --- | --- | --- |

| getStats | (): array{directory, files, size} | Cache directory statistics |

| gc | (): int | Garbage collect expired entries |

← Previous: Collection

Validation

Clone this wiki locally