exec(" CREATE TABLE IF NOT EXISTS `app_cache` ( `cache_key` VARCHAR(128) NOT NULL PRIMARY KEY, `cache_value` MEDIUMTEXT NOT NULL, `expires_at` INT UNSIGNED NOT NULL, INDEX `idx_app_cache_expires` (`expires_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; "); $ensured = true; } catch (Throwable $e) { error_log("ensure_app_cache_table error: " . $e->getMessage()); } } /** * Haalt een item op uit de cache. * Controleert eerst het runtime statisch geheugen, vervolgens MariaDB. */ function fociz_cache_get(string $key, $default = null) { static $memoryCache = []; $now = time(); // 1. Runtime memory check (0ms) if (isset($memoryCache[$key])) { if ($memoryCache[$key]['expires_at'] > $now) { return $memoryCache[$key]['value']; } unset($memoryCache[$key]); } // 2. Database check (< 0.5ms) try { $db = get_db_connection(); ensure_app_cache_table($db); $stmt = $db->prepare("SELECT cache_value, expires_at FROM app_cache WHERE cache_key = ?"); $stmt->execute([$key]); $row = $stmt->fetch(); if ($row) { if ((int)$row['expires_at'] > $now) { $decoded = json_decode($row['cache_value'], true); $val = ($decoded !== null || $row['cache_value'] === 'null') ? $decoded : $row['cache_value']; $memoryCache[$key] = [ 'value' => $val, 'expires_at' => (int)$row['expires_at'] ]; return $val; } else { // Verlopen item direct opruimen $del = $db->prepare("DELETE FROM app_cache WHERE cache_key = ?"); $del->execute([$key]); } } } catch (Throwable $e) { error_log("fociz_cache_get error for {$key}: " . $e->getMessage()); } return $default; } /** * Slaat een item op in de cache met een bepaalde levensduur in seconden. */ function fociz_cache_set(string $key, $value, int $ttlSeconds = 60): bool { static $memoryCache = []; $now = time(); $expiresAt = $now + max(1, $ttlSeconds); // 1. Sla op in runtime memory $memoryCache[$key] = [ 'value' => $value, 'expires_at' => $expiresAt ]; // 2. Sla op in database try { $db = get_db_connection(); ensure_app_cache_table($db); $valToStore = is_string($value) ? $value : json_encode($value, JSON_UNESCAPED_UNICODE); $stmt = $db->prepare(" INSERT INTO app_cache (cache_key, cache_value, expires_at) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE cache_value = VALUES(cache_value), expires_at = VALUES(expires_at) "); return $stmt->execute([$key, $valToStore, $expiresAt]); } catch (Throwable $e) { error_log("fociz_cache_set error for {$key}: " . $e->getMessage()); return false; } } /** * Verwijdert een specifiek item uit de cache. */ function fociz_cache_delete(string $key): bool { try { $db = get_db_connection(); ensure_app_cache_table($db); $stmt = $db->prepare("DELETE FROM app_cache WHERE cache_key = ?"); return $stmt->execute([$key]); } catch (Throwable $e) { return false; } } /** * Verwijdert alle items met een bepaald voorvoegsel (bijv. 'ms_events_1_') */ function fociz_cache_delete_pattern(string $prefix): bool { try { $db = get_db_connection(); ensure_app_cache_table($db); $stmt = $db->prepare("DELETE FROM app_cache WHERE cache_key LIKE ?"); return $stmt->execute([$prefix . '%']); } catch (Throwable $e) { return false; } }