- Change FileCache CACHE_PATH from relative to absolute path - Change FileCacheCleaner cache folder to absolute path - Resolves read-only file system issue in production containers - Cache now uses writable /var/www/html/storage/cache location
Cache-System mit Decorator-Pattern
Dieses erweiterte Cache-System nutzt das Decorator-Pattern für maximale Flexibilität und Erweiterbarkeit. Verschiedene Cache-Features können modular kombiniert werden, ohne die Kernfunktionalität zu beeinträchtigen.
🏗️ Architektur
Kernkomponenten
CacheInterface: Basis-Interface für alle Cache-Implementierungen- Cache-Driver: Konkrete Implementierungen (FileCache, RedisCache, etc.)
- Cache-Decorators: Erweitern die Funktionalität ohne Änderung der Basis-Implementierung
- CacheBuilder: Fluent API für einfache Decorator-Komposition
Decorator-Pattern Vorteile
✅ Modular: Features können einzeln hinzugefügt/entfernt werden
✅ Performant: Kein Overhead durch nicht genutzte Features
✅ Erweiterbar: Neue Decorators ohne Änderung bestehender Klassen
✅ Testbar: Jeder Decorator kann isoliert getestet werden
🔧 Verfügbare Decorators
1. MetricsDecoratedCache
Performance-Monitoring und Metriken
$cacheMetrics = new \App\Framework\Cache\Metrics\CacheMetrics();
$cache = new \App\Framework\Cache\Metrics\MetricsDecoratedCache(
$baseCache,
$cacheMetrics,
'MyCache',
$performanceCollector,
true
);
Features:
- Hit/Miss-Ratios
- Operation-Timing
- Speicherverbrauch-Tracking
- Fehler-Zählung
- Integration in das Framework Performance-System
Metriken:
cache_hits/cache_missescache_operations_totalcache_retrieved_bytes/cache_stored_bytescache_remember_callback_duration
2. ValidationCacheDecorator
Sicherheit und Datenintegrität
$config = [
'max_key_length' => 250,
'max_value_size' => 1024 * 1024, // 1MB
'strict_key_validation' => true,
'forbidden_types' => ['resource'],
'reserved_prefixes' => ['__', 'system:'],
];
$cache = new ValidationCacheDecorator($baseCache, $config);
Validierungsregeln:
- Key-Länge und -Format
- Value-Größe und -Typ
- TTL-Bereiche
- Verbotene Patterns
- Reservierte Prefixes
3. EventCacheDecorator
Event-basierte Architektur
$cache = new EventCacheDecorator($baseCache, $eventDispatcher);
Events:
CacheHit- Bei Cache-TreffernCacheMiss- Bei Cache-FehlernCacheSet- Beim Setzen von WertenCacheDelete- Beim Löschen von KeysCacheClear- Beim Cache-Leeren
4. LoggingCacheDecorator
Detailliertes Logging
$cache = new LoggingCacheDecorator($baseCache);
Log-Outputs:
Cache HIT: user:123 (value: array)
Cache SET: session:abc = string, TTL: 3600, Success: YES
Cache MISS: product:456
5. CompressionCacheDecorator
Automatische Komprimierung
$cache = new CompressionCacheDecorator(
$baseCache,
new GzipCompression(),
new PhpSerializer()
);
🚀 Verwendung
Einfache Decorator-Komposition
// Manuell
$cache = new FileCache('/path/to/cache');
$cache = new ValidationCacheDecorator($cache, $validationConfig);
$cacheMetrics = new \App\Framework\Cache\Metrics\CacheMetrics();
$cache = new \App\Framework\Cache\Metrics\MetricsDecoratedCache($cache, $cacheMetrics, 'MyCache', $performanceCollector);
$cache = new LoggingCacheDecorator($cache);
// Mit CacheBuilder (empfohlen)
$cache = CacheBuilder::create(new FileCache('/path/to/cache'))
->withValidation($validationConfig)
->withMetrics($performanceCollector)
->withEvents($eventDispatcher)
->withLogging()
->build();
Vorgefertigte Konfigurationen
// Für Production: Performance-optimiert
$cache = CacheBuilder::createPerformant(
new RedisCache($redisConnection),
$performanceCollector,
new GzipCompression(),
new PhpSerializer()
);
// Für Development: Vollständiges Monitoring
$cache = CacheBuilder::createDevelopment(
new FileCache('/tmp/cache'),
$performanceCollector,
$eventDispatcher,
['strict_key_validation' => true]
);
// Vollausstattung
$cache = CacheBuilder::createFull(
new RedisCache($redisConnection),
$performanceCollector,
$eventDispatcher,
new GzipCompression(),
new PhpSerializer(),
['max_value_size' => 512 * 1024] // 512KB
);
Event-Handler Beispiele
// Cache-Statistiken sammeln
$eventDispatcher->addListener(CacheHit::class, function(CacheHit $event) {
$this->statsCollector->recordHit($event->key, $event->valueSize);
});
// Warnung bei großen Cache-Werten
$eventDispatcher->addListener(CacheSet::class, function(CacheSet $event) {
if ($event->valueSize > 100 * 1024) { // 100KB
$this->logger->warning("Large cache value set", [
'key' => $event->key,
'size' => $event->valueSize
]);
}
});
// Cache-Miss Debugging
$eventDispatcher->addListener(CacheMiss::class, function(CacheMiss $event) {
$this->debugLogger->debug("Cache miss for key: {$event->key}");
});
🔒 Sicherheitsfeatures
Validation-Konfiguration
$secureConfig = [
// Basis-Validierung
'max_key_length' => 200,
'max_value_size' => 512 * 1024, // 512KB
'min_ttl' => 60, // Min. 1 Minute
'max_ttl' => 7 * 24 * 3600, // Max. 1 Woche
// Strikte Validierung
'strict_key_validation' => true,
'strict_object_validation' => true,
// Verbotene Elemente
'forbidden_types' => ['resource'],
'forbidden_key_patterns' => [
'/\.\./', // Directory traversal
'/\/\//', // Double slashes
'/\x00/', // Null bytes
'/[<>]/', // HTML-like chars
],
// Reservierte Prefixes
'reserved_prefixes' => [
'__',
'system:',
'internal:',
'framework:',
],
// Custom Validator
'value_validator' => function($value) {
// Keine serialisierten Objects mit kritischen Methoden
if (is_object($value)) {
$dangerousMethods = ['__destruct', '__wakeup', '__toString'];
$reflection = new ReflectionClass($value);
foreach ($dangerousMethods as $method) {
if ($reflection->hasMethod($method)) {
return false;
}
}
}
return true;
}
];
📊 Performance-Integration
Die MetricsDecoratedCache integriert sich nahtlos in das Framework Performance-System:
// Cache-Metriken im Performance Report
Cache Category: 45.2 ms (156 calls)
- cache_hits: 142
- cache_misses: 14
- cache_operations_total: 156
- cache_retrieved_bytes: 45.2 KB
- cache_stored_bytes: 12.8 KB
🧪 Testing
Unit Tests für Decorators
class MetricsDecoratedCacheTest extends TestCase
{
public function testRecordsHitMetrics(): void
{
$mockCache = $this->createMock(Cache::class);
$collector = $this->createMock(PerformanceCollector::class);
$mockCache->method('get')->willReturn(CacheItem::hit('key', 'value'));
$collector->expects($this->once())
->method('increment')
->with('cache_hits', PerformanceCategory::CACHE, 1);
$cacheMetrics = new \App\Framework\Cache\Metrics\CacheMetrics();
$decorator = new \App\Framework\Cache\Metrics\MetricsDecoratedCache($mockCache, $cacheMetrics, 'Test', $collector);
$decorator->get('test-key');
}
}
🔄 Migration von alten Systemen
// Alt: Direkte Cache-Nutzung
$cache = new FileCache('/path');
$value = $cache->get('key');
// Neu: Mit Decorators (Backward-Compatible)
$cache = CacheBuilder::create(new FileCache('/path'))
->withMetrics($performanceCollector)
->build();
$value = $cache->get('key'); // Gleiche API!
🎯 Best Practices
1. Decorator-Reihenfolge beachten
// ✅ Richtig: Validation → Compression → Metrics → Logging
CacheBuilder::create($baseCache)
->withValidation($config) // Zuerst validieren
->withCompression($algo, $ser) // Dann komprimieren
->withMetrics($collector) // Performance messen
->withLogging() // Zuletzt loggen
->build();
// ❌ Falsch: Logging vor Validation
// Würde auch invalide Operationen loggen
2. Production vs Development
// Production: Minimal, performant
if ($isProduction) {
$cache = CacheBuilder::createPerformant($baseCache, $collector, $compression, $serializer);
} else {
// Development: Vollständiges Monitoring
$cache = CacheBuilder::createDevelopment($baseCache, $collector, $eventDispatcher, $validationConfig);
}
3. Conditional Decorators
$builder = CacheBuilder::create($baseCache);
if ($enableMetrics) {
$builder->withMetrics($performanceCollector);
}
if ($enableValidation) {
$builder->withValidation($validationConfig);
}
if ($debugMode) {
$builder->withLogging();
}
$cache = $builder->build();
Das Decorator-Pattern macht das Cache-System extrem flexibel und erweiterbar, ohne Komplexität oder Performance-Einbußen für nicht genutzte Features.