fastCache->get(...$identifiers); $allItems = []; $missedIdentifiers = []; foreach ($identifiers as $identifier) { $item = $fastResult->getItem($identifier instanceof CacheKey ? $identifier : CacheKey::fromString($identifier->toString())); if ($item->isHit) { $allItems[] = $item; } else { $missedIdentifiers[] = $identifier; } } // Fallback to slow cache for missed items if (! empty($missedIdentifiers)) { $slowResult = $this->slowCache->get(...$missedIdentifiers); foreach ($slowResult->getItems() as $item) { if ($item->isHit && $item->key instanceof CacheKey) { // Cache in fast cache if appropriate if ($this->shouldCacheInFast($item->value)) { $this->fastCache->set(CacheItem::forSet($item->key, $item->value, self::getDefaultFastCacheTTL())); } } $allItems[] = $item; } } return CacheResult::fromItems(...$allItems); } public function set(CacheItem ...$items): bool { if (empty($items)) { return true; } $slowSuccess = $this->slowCache->set(...$items); // Also set in fast cache if appropriate $fastItems = []; foreach ($items as $item) { if ($this->shouldCacheInFast($item->value)) { $fastTtl = $item->ttl !== null ? Duration::fromSeconds(min($item->ttl->toSeconds(), self::FAST_CACHE_TTL_SECONDS)) : self::getDefaultFastCacheTTL(); $fastItems[] = CacheItem::forSet($item->key, $item->value, $fastTtl); } } $fastSuccess = true; if (! empty($fastItems)) { $fastSuccess = $this->fastCache->set(...$fastItems); } return $slowSuccess && $fastSuccess; } public function forget(CacheIdentifier ...$identifiers): bool { if (empty($identifiers)) { return true; } $s1 = $this->fastCache->forget(...$identifiers); $s2 = $this->slowCache->forget(...$identifiers); return $s1 && $s2; } public function clear(): bool { $s1 = $this->fastCache->clear(); $s2 = $this->slowCache->clear(); return $s1 && $s2; } public function has(CacheIdentifier ...$identifiers): array { if (empty($identifiers)) { return []; } $fastResults = $this->fastCache->has(...$identifiers); $results = []; $toCheckInSlow = []; foreach ($identifiers as $identifier) { $keyString = $identifier->toString(); if ($fastResults[$keyString] ?? false) { $results[$keyString] = true; } else { $toCheckInSlow[] = $identifier; $results[$keyString] = false; // Default to false, will be updated if found in slow } } // Check missed items in slow cache and warm up fast cache if (! empty($toCheckInSlow)) { $slowResults = $this->slowCache->has(...$toCheckInSlow); foreach ($toCheckInSlow as $identifier) { $keyString = $identifier->toString(); if ($slowResults[$keyString] ?? false) { $results[$keyString] = true; // Warm up fast cache if it's a key identifier if ($identifier instanceof CacheKey) { $slowResult = $this->slowCache->get($identifier); $item = $slowResult->getItem($identifier); if ($item->isHit && $this->shouldCacheInFast($item->value)) { $this->fastCache->set(CacheItem::forSet($identifier, $item->value, self::getDefaultFastCacheTTL())); } } } } } return $results; } public function remember(CacheKey $key, callable $callback, ?Duration $ttl = null): CacheItem { $item = $this->get($key); if ($item->isHit) { return $item; } // Wert generieren, speichern und zurückgeben $value = $callback(); $this->set($key, $value, $ttl); // Erstelle neuen CacheItem als Treffer return CacheItem::hit($key, $value); } private function shouldCacheInFast(mixed $value): bool { // Wenn es bereits ein String ist (serialisiert), nutze dessen Länge if (is_string($value)) { return strlen($value) <= self::MAX_FAST_CACHE_SIZE; } // Für Arrays: Schnelle Heuristik ohne Serialisierung if (is_array($value)) { $elementCount = count($value, COUNT_RECURSIVE); // Grobe Schätzung: 50 Bytes pro Element $estimatedSize = $elementCount * 50; return $estimatedSize <= self::MAX_FAST_CACHE_SIZE; } // Für Objekte: Konservativ - nicht in fast cache if (is_object($value)) { return false; } // Primitive Typen: Immer cachen return true; } /** * Get the underlying cache driver (uses slow cache as primary) */ public function getDriver(): ?CacheDriver { // Try slow cache first as it's typically the primary storage if ($this->slowCache instanceof DriverAccessible) { return $this->slowCache->getDriver(); } // If slow cache doesn't have driver access, try fast cache if ($this->fastCache instanceof DriverAccessible) { return $this->fastCache->getDriver(); } // Check if the cache layers are directly drivers if ($this->slowCache instanceof CacheDriver) { return $this->slowCache; } if ($this->fastCache instanceof CacheDriver) { return $this->fastCache; } return null; } /** * Check if the underlying driver supports a specific interface */ public function driverSupports(string $interface): bool { $driver = $this->getDriver(); return $driver !== null && $driver instanceof $interface; } /** * Get the slow cache (primary storage layer) */ public function getSlowCache(): Cache { return $this->slowCache; } /** * Get the fast cache (quick access layer) */ public function getFastCache(): Cache { return $this->fastCache; } }