Skip to content

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á v Cache::init())
  • Oprávnění: 0770 na adresáře, 0660 na 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á data
  • null – 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:

  1. $path . '/*/*/*.php' – všechny cache soubory
  2. $path . '/*/*' – adresáře druhé úrovně
  3. $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 souboru
  • array – 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

  1. DB query results – Cachuj výsledky SELECT, které se opakují
  2. YAML config – Cachuj parsované config soubory
  3. API responses – Cachuj externí API volání
  4. Expensive computations – Math, parsing, transformations