Popis Cache třídy
Finální třída Cache v core/Cache/Cache.php – vlastní implementace bez dependencies. Minimalistická, transparentní, určená pro malý tým.
Třída Cache
Statická třída pro file-based cachování. Bez ORM, bez Stash, bez magic. Co vidíš v kódu, to se děje.
Design Goals
- ✓ Minimal IO
- ✓ TTL uložen v file
mtime - ✓ Atomic writes (tmp → rename)
- ✓ Hashed directory structure (2-level:
XX/YY/hash.php)
Konstanta – Default TTL
Cache::SECONDS // 3600 sekund = 1 hodina
Lze přepsat v třetím parametru metod set() a file().
Úložiště
- Cesta:
$path(inicializovaná vCache::init()) - Oprávnění:
0770na adresáře,0660na soubory (umask-based) - Struktura:
path/ab/cd/abcdefg1234567890.php ab,cd= první 4 znaky MD5(key)- Zbývající 28 znaků MD5 = zbytek filename
Inicializace
// Voláno v bootstrap paths.php
Cache::init('/path/to/cache/dir');
Veřejné metody
init(string $path): void
Inicializuje cache storage path. Volej jednou v bootstrapu.
Cache::init(DIR . '/var/cache');
set(string $key, mixed $value, int $ttl = self::SECONDS): void
Uloží data do cache s TTL.
$hash = md5($key);
$dir = $path . '/' . $hash[0] . $hash[1] . '/' . $hash[2] . $hash[3];
// Vytvoří PHP soubor atomicky
$file = $dir . '/' . $hash . '.php';
$tmp = $file . '.tmp';
$php = "<?php\n return " . var_export($value, true) . ";\n";
file_put_contents($tmp, $php, LOCK_EX);
rename($tmp, $file);
// TTL = filemtime
touch($file, time() + $ttl);
Argumenty:
$key– Cache key (string, libovolný)$value– Data (mixed – struktury, objekty, primitives)$ttl– Expiration v sekundách (default: 3600)
Příklad:
Cache::set('users_all', $userData, 1800); // 30 minut
get(string $key): mixed
Načte data z cache. Vrací null pokud neexistuje nebo je expirovaná.
$hash = md5($key);
$file = $path . '/' . $hash[0] . $hash[1] . '/' . $hash[2] . $hash[3] . '/' . $hash . '.php';
$mtime = @filemtime($file);
if ($mtime === false || $mtime < time()) {
@unlink($file);
return null;
}
if (!is_file($file)) {
return null;
}
$data = include $file;
return $data === false ? null : $data;
Vrací:
mixed– Uložená datanull– Cache miss nebo expirace
Příklad:
$users = Cache::get('users_all');
if ($users === null) {
$users = DB::results("SELECT * FROM users");
Cache::set('users_all', $users, 1800);
}
delete(string $key): void
Smaž konkrétní cache položku okamžitě.
@unlink($path . '/' . $hash[0] . $hash[1] . '/' . $hash[2] . $hash[3] . '/' . $hash . '.php');
Příklad:
// Po UPDATE musíš invalidovat cache
DB::query("UPDATE users SET name = ? WHERE id = ?", [$name, $id]);
Cache::delete('users_all');
clear(): void
Vymaž VŠECHNY cache soubory. Tři glob pro hashed strukturu:
$path . '/*/*/*.php'– všechny cache soubory$path . '/*/*'– adresáře druhé úrovně$path . '/*'– adresáře první úrovně
foreach (glob(self::$path . '/*/*/*.php') as $file) {
@unlink($file);
}
foreach (glob(self::$path . '/*/*') as $dir) {
@rmdir($dir);
}
foreach (glob(self::$path . '/*') as $dir) {
@rmdir($dir);
}
purge(): void
Odstraň EXPIROVANÉ cache soubory (založeno na filemtime()).
$now = time();
foreach (glob(self::$path . '/*/*/*.php') as $file) {
if (@filemtime($file) < $now) {
@unlink($file);
}
}
file(string $filepath, string $type = 'yaml', int $ttl = self::SECONDS): array
Speciální metoda pro cachování obsahu souborů. Automaticky cachuje parsované soubory.
$key = md5($filepath);
$cached = self::get($key);
if ($cached !== null) {
return $cached;
}
if ($type === 'yaml') {
$data = Yaml::parseFile($filepath) ?? [];
self::set($key, $data, $ttl);
return $data;
}
return [];
Argumenty:
$filepath– Absolutní cesta k souboru$type– Typ souboru (momentálně:'yaml')$ttl– Expirace v sekundách (default: 3600)
Vrací:
array– Parsovaný obsah souboruarray– Prázdné pole pokud soubor neexistuje
Příklad:
// První volání: parsuje + cachuje
$settings = Cache::file('app/config/settings.yaml');
// Druhé volání: vrací z cache
$settings = Cache::file('app/config/settings.yaml');
Privátní properties
$path
private static ?string $path = null;
Inicializovaná v init(). Cesta k cache storage adresáři.
Chování
Cache hit
Cache::set('key', ['a' => 1]);
$data = Cache::get('key');
// Vrací: ['a' => 1]
Cache miss (neexistuje)
$data = Cache::get('nonexistent');
// Vrací: null
Cache miss (expirovaná)
Cache::set('key', $data, 1); // TTL = 1 sekunda
sleep(2);
$data = Cache::get('key');
// Vrací: null (a smaže soubor)
File format
<?php
return array (
'key' => 'value',
);
Uloženo pomocí var_export() pro transparentnost a výkon.
Výhody a omezení
✓ Výhody
- Žádné dependencies – Stash je pryč
- Atomické writes – tmp file + rename (no corruption on crash)
- TTL v mtime – OS spravuje expirace transparentně
- Transparent – čti soubory přímo v debuggingu
- Hashovaná struktura – miliony souborů bez FS problémů
⚠️ Omezení
- Filesystem-only – nejde Redis, Memcached, atd.
- Lokální pouze – multi-server cache potřebuje ruční řešení
- Malá data – optimizováno pro konfiguraci, DB výsledky, ne binární data
Typické use cases
- DB query results – Cachuj výsledky
SELECT, které se opakují - YAML config – Cachuj parsované config soubory
- API responses – Cachuj externí API volání
- Expensive computations – Math, parsing, transformations