High-performance caching system with multiple drivers, cache tagging, and advanced features. The caching system provides a unified interface for various storage backends including Redis, Memcached, file-based, and database caching with support for cache tags, TTL, and atomic operations.
Central cache management class that provides a unified interface for all caching operations. The CacheManager handles driver initialization, configuration management, and provides factory methods for creating cache instances.
Configure cache drivers and settings.
use Forge\Cache\CacheManager;
use Forge\Cache\Drivers\RedisDriver;
use Forge\Cache\Drivers\FileDriver;
use Forge\Cache\Drivers\DatabaseDriver;
// Create cache manager
$cacheManager = new CacheManager();
// Configure default cache store
$cacheManager->setDefaultStore('redis');
// Configure cache stores
$cacheManager->setStores([
    'redis' => [
        'driver' => RedisDriver::class,
        'connection' => 'default',
        'prefix' => 'forge_cache:',
        'ttl' => 3600
    ],
    'file' => [
        'driver' => FileDriver::class,
        'path' => storage_path('framework/cache'),
        'prefix' => 'forge_',
        'ttl' => 7200
    ],
    'database' => [
        'driver' => DatabaseDriver::class,
        'table' => 'cache',
        'connection' => 'default',
        'prefix' => 'forge_',
        'ttl' => 86400
    ],
    'array' => [
        'driver' => 'array',
        'ttl' => 300
    ]
]);
// Get cache instance
$cache = $cacheManager->store('redis');
$defaultCache = $cacheManager->store(); // Uses default store
// Configure global settings
$cacheManager->setConfig([
    'prefix' => 'app_',
    'ttl' => 3600,
    'serialize' => true,
    'compression' => true,
    'encryption' => false
]);Store, retrieve, and delete cache items.
// Store data in cache
$cache->put('user:1', $userData, 3600); // TTL in seconds
$cache->put('settings', $settings, now()->addHours(2));
// Store if not exists
$cache->add('counter', 1, 300); // Returns true if added, false if exists
// Retrieve data from cache
$user = $cache->get('user:1');
$settings = $cache->get('settings', function() {
    // This callback is executed if key doesn't exist
    return $this->loadSettingsFromDatabase();
});
// Check if key exists
if ($cache->has('user:1')) {
    $user = $cache->get('user:1');
}
// Delete cache items
$cache->forget('user:1');
$cache->delete('settings');
// Delete multiple keys
$cache->deleteMultiple(['user:1', 'user:2', 'user:3']);
// Clear all cache
$cache->flush();
// Get and delete (pull)
$user = $cache->pull('user:1'); // Gets and removes from cache
// Increment/decrement
$cache->increment('visits');
$cache->increment('visits', 5);
$cache->decrement('stock');
$cache->decrement('stock', 2);
// Remember pattern
$users = $cache->remember('users.active', 3600, function() {
    return User::where('active', true)->get();
});
// Remember forever
$countries = $cache->rememberForever('countries', function() {
    return Country::all();
});Organize and manage related cache items using tags.
// Store with tags
$cache->tags(['users', 'profiles'])->put('user:1', $userData, 3600);
$cache->tags(['posts', 'recent'])->put('posts.recent', $recentPosts, 1800);
// Retrieve with tags
$user = $cache->tags(['users'])->get('user:1');
$posts = $cache->tags(['posts', 'recent'])->get('posts.recent');
// Flush specific tags
$cache->tags(['users'])->flush(); // Remove all items tagged with 'users'
$cache->tags(['posts', 'recent'])->flush(); // Remove items with both tags
// Multiple tags operations
$cache->tags(['users', 'admins'])->put('admin:1', $adminData, 3600);
// Get all keys for a tag
$userKeys = $cache->tags(['users'])->getKeys();
// Check if tagged item exists
if ($cache->tags(['users'])->has('user:1')) {
    // Process cached user data
}
// Tagged remember pattern
$admins = $cache->tags(['users', 'admins'])->remember('admins.all', 3600, function() {
    return User::where('role', 'admin')->get();
});
// Clear cache by tags (useful for cache invalidation)
$cache->tags(['user:1', 'posts'])->flush(); // Clear user's posts
$cache->tags(['category:tech'])->flush(); // Clear tech category cachePrevent cache stampedes with atomic locking.
// Acquire lock
$lock = $cache->lock('expensive-operation', 30); // 30 second timeout
if ($lock->get()) {
    try {
        // Perform expensive operation
        $data = $this->performExpensiveOperation();
        
        // Cache the result
        $cache->put('expensive-data', $data, 3600);
        
        return $data;
    } finally {
        $lock->release();
    }
}
// Wait for lock with timeout
$lock = $cache->lock('report-generation', 60);
if ($lock->block(10)) { // Wait up to 10 seconds
    try {
        // Generate report
        $report = $this->generateReport();
        
        // Cache result
        $cache->put('report:latest', $report, 3600);
        
        return $report;
    } finally {
        $lock->release();
    }
} else {
    throw new \Exception('Could not acquire lock for report generation');
}
// Scoped locks
$cache->lock('user:1:update', 30)->get(function() use ($cache, $userId) {
    // This code is executed atomically
    $user = $cache->get('user:1');
    $user['last_seen'] = now();
    $cache->put('user:1', $user, 3600);
});
// Check if lock exists
if ($cache->lock('maintenance')->exists()) {
    echo "Maintenance in progress";
}
// Force release lock
$cache->lock('stuck-operation')->forceRelease();Different storage backends for caching with specific features and configurations. Each driver provides optimized performance for different use cases and environments.
High-performance Redis-based caching with advanced features.
use Forge\Cache\Drivers\RedisDriver;
use Forge\Redis\RedisManager;
// Configure Redis driver
$redisDriver = new RedisDriver([
    'connection' => 'cache',
    'prefix' => 'forge_cache:',
    'serializer' => 'json', // json, php, igbinary, msgpack
    'compression' => true,
    'ttl' => 3600
]);
// Advanced Redis configuration
$redisDriver->setRedis(new RedisManager([
    'scheme' => 'tcp',
    'host' => '127.0.0.1',
    'port' => 6379,
    'password' => null,
    'database' => 1,
    'timeout' => 5.0,
    'read_timeout' => 10.0,
    'persistent' => true,
    'prefix' => 'forge:',
    'serializer' => Redis::SERIALIZER_JSON,
    'compression' => Redis::COMPRESSION_LZ4,
    'retry_interval' => 100,
    'retry_timeout' => 2000
]));
// Redis-specific operations
$redisDriver->set('user:1', $userData, 3600);
// Use Redis data structures
$redisDriver->lpush('recent_users', 'user:1');
$redisDriver->ltrim('recent_users', 0, 99); // Keep last 100
$redisDriver->sadd('online_users', 'user:1');
$redisDriver->srem('online_users', 'user:2');
$redisDriver->zadd('leaderboard', 100, 'user:1');
$redisDriver->zincrby('leaderboard', 10, 'user:1');
// Hash operations
$redisDriver->hset('user:1:session', 'last_seen', time());
$redisDriver->hget('user:1:session', 'last_seen');
$redisDriver->hgetall('user:1:session');
// Set expiration
$redisDriver->expire('temp_key', 300); // 5 minutes
$redisDriver->expireat('temp_key', strtotime('+1 hour'));
// Check TTL
$ttl = $redisDriver->ttl('user:1'); // Returns seconds remaining
// Persistence control
$redisDriver->save(); // Synchronous save
$redisDriver->bgsave(); // Background save
// Pipeline operations for bulk processing
$redisDriver->pipeline(function($pipe) {
    for ($i = 0; $i < 1000; $i++) {
        $pipe->set("key:{$i}", "value:{$i}", 3600);
    }
});Configure Redis cluster for high availability.
$redisDriver->setRedis(new RedisManager([
    'cluster' => true,
    'clusters' => [
        'default' => [
            ['host' => '127.0.0.1', 'port' => 7000],
            ['host' => '127.0.0.1', 'port' => 7001],
            ['host' => '127.0.0.1', 'port' => 7002],
        ],
        'cache' => [
            ['host' => '127.0.0.1', 'port' => 7003],
            ['host' => '127.0.0.1', 'port' => 7004],
            ['host' => '127.0.0.1', 'port' => 7005],
        ]
    ],
    'options' => [
        'timeout' => 5.0,
        'read_timeout' => 10.0,
        'persistent' => true,
        'failover' => 'error', // error, distribute, none
        'slave_failover' => 'distribute'
    ]
]));
// Redis Sentinel configuration
$redisDriver->setRedis(new RedisManager([
    'sentinel' => true,
    'sentinels' => [
        ['host' => 'sentinel1', 'port' => 26379],
        ['host' => 'sentinel2', 'port' => 26379],
        ['host' => 'sentinel3', 'port' => 26379]
    ],
    'service' => 'mymaster',
    'password' => 'redis_password',
    'database' => 0
]));File-based caching with directory organization.
use Forge\Cache\Drivers\FileCacheDriver;
// Configure file driver
$fileDriver = new FileCacheDriver([
    'path' => storage_path('framework/cache'),
    'prefix' => 'forge_',
    'permission' => 0644,
    'directory_permission' => 0755,
    'ttl' => 7200,
    'serialize' => true,
    'compression' => false,
    'encryption' => false
]);
// Advanced file cache configuration
$fileDriver->setConfig([
    'path' => storage_path('framework/cache/data'),
    'hash_directory' => true, // Use hash-based directory structure
    'directory_level' => 2, // Number of directory levels
    'file_extension' => '.cache',
    'max_file_size' => 1048576, // 1MB max file size
    'gc_probability' => 0.01, // 1% garbage collection chance
    'gc_divisor' => 100,
    'lock_file' => true, // Use file locking
    'lock_timeout' => 30 // 30 seconds
]);
// Organize cache by directories
$fileDriver->put('config/app', $appConfig, 3600);
$fileDriver->put('config/database', $dbConfig, 3600);
$fileDriver->put('views/home', $homeView, 1800);
$fileDriver->put('data/users', $userData, 3600);
// Use different storage paths
$fileDriver->setPath(storage_path('framework/cache/views'));
$fileDriver->put('template:main', $templateData, 86400);
$fileDriver->setPath(storage_path('framework/cache/sessions'));
$fileDriver->put('session:' . $sessionId, $sessionData, 1800);
// File-specific operations
$fileDriver->clean(); // Remove expired files
$fileDriver->gc(); // Run garbage collection
$fileDriver->optimize(); // Optimize storage structure
// Get cache statistics
$stats = $fileDriver->getStats();
echo "Total files: " . $stats['files'];
echo "Total size: " . $stats['size'];
echo "Expired files: " . $stats['expired'];
// Backup cache files
$fileDriver->backup(storage_path('backups/cache-' . date('Y-m-d') . '.tar.gz'));
// Restore cache files
$fileDriver->restore(storage_path('backups/cache-2024-01-01.tar.gz'));Database-based caching with automatic table management.
use Forge\Cache\Drivers\DatabaseCacheDriver;
// Configure database driver
$dbDriver = new DatabaseCacheDriver([
    'table' => 'cache',
    'connection' => 'default',
    'prefix' => 'forge_',
    'ttl' => 86400,
    'serialize' => true,
    'compression' => true,
    'encryption' => false,
    'chunk_size' => 1000
]);
// Database cache table schema
$schema = "
CREATE TABLE cache (
    key VARCHAR(255) PRIMARY KEY,
    value TEXT NOT NULL,
    expiration INT NOT NULL,
    tags TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_expiration (expiration),
    INDEX idx_tags (tags(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
";
// Advanced database cache configuration
$dbDriver->setConfig([
    'table' => 'cache',
    'connection' => 'cache',
    'chunk_size' => 500,
    'batch_size' => 50,
    'cleanup_batch_size' => 100,
    'gc_frequency' => 0.1, // 10% chance of cleanup
    'index_tags' => true,
    'index_expiration' => true,
    'partition_by_date' => false,
    'archive_old' => true,
    'archive_table' => 'cache_archive'
]);
// Database-specific operations
$dbDriver->clean(); // Remove expired entries
$dbDriver->vacuum(); // Optimize table
$dbDriver->analyze(); // Update statistics
// Batch operations
$dbDriver->putMany([
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
], 3600);
$values = $dbDriver->getMany(['key1', 'key2', 'key3']);
// Tagged database cache
$dbDriver->tags(['users', 'recent'])->put('users.recent', $users, 3600);
// Database cache statistics
$stats = $dbDriver->getStats();
echo "Total entries: " . $stats['total'];
echo "Expired entries: " . $stats['expired'];
echo "Average size: " . $stats['avg_size'];
// Cleanup operations
$deleted = $dbDriver->cleanup(); // Remove expired entries
$optimized = $dbDriver->optimize(); // Optimize storageCommon caching patterns and strategies for different use cases. These patterns help implement efficient caching strategies for various application scenarios.
Application manages cache explicitly.
class UserRepository
{
    private $cache;
    
    public function __construct(CacheManager $cache)
    {
        $this->cache = $cache;
    }
    
    public function find($id)
    {
        $key = "user:{$id}";
        
        // Try to get from cache
        $user = $this->cache->get($key);
        
        if ($user === null) {
            // Not in cache, get from database
            $user = User::find($id);
            
            if ($user) {
                // Store in cache
                $this->cache->put($key, $user, 3600);
                $this->cache->tags(['users', "user:{$id}"])->put($key, $user, 3600);
            }
        }
        
        return $user;
    }
    
    public function update($id, array $data)
    {
        $user = User::find($id);
        
        if ($user) {
            $user->update($data);
            
            // Update cache
            $this->cache->put("user:{$id}", $user, 3600);
            
            // Invalidate related caches
            $this->cache->tags(['users'])->flush();
            $this->cache->tags(['user:{$id}'])->flush();
        }
        
        return $user;
    }
    
    public function delete($id)
    {
        User::destroy($id);
        
        // Remove from cache
        $this->cache->forget("user:{$id}");
        
        // Invalidate related caches
        $this->cache->tags(['users'])->flush();
        $this->cache->tags(['user:{$id}'])->flush();
    }
}Cache is updated automatically on data changes.
class CachedUserRepository
{
    private $cache;
    
    public function __construct(CacheManager $cache)
    {
        $this->cache = $cache;
    }
    
    public function create(array $data)
    {
        // Create user in database
        $user = User::create($data);
        
        // Automatically cache the new user
        $this->cache->tags(['users', "user:{$user->id}"])->put(
            "user:{$user->id}",
            $user,
            3600
        );
        
        // Invalidate user lists
        $this->cache->tags(['user_lists'])->flush();
        
        return $user;
    }
    
    public function update($id, array $data)
    {
        // Update user in database
        $user = User::find($id);
        
        if ($user) {
            $user->update($data);
            
            // Update cache immediately
            $this->cache->tags(['users', "user:{$id}"])->put(
                "user:{$id}",
                $user,
                3600
            );
            
            // Invalidate related caches
            $this->cache->tags(['user_lists', 'user:{$id}:related'])->flush();
        }
        
        return $user;
    }
    
    public function getAll($page = 1, $perPage = 20)
    {
        $key = "users:page:{$page}:per_page:{$perPage}";
        
        return $this->cache->tags(['user_lists'])->remember($key, 1800, function() use ($page, $perPage) {
            return User::paginate($perPage, ['*'], 'page', $page);
        });
    }
}Pre-populate cache with frequently accessed data.
class CacheWarmer
{
    private $cache;
    
    public function __construct(CacheManager $cache)
    {
        $this->cache = $cache;
    }
    
    public function warmCache()
    {
        // Warm user data
        $this->warmUsers();
        
        // Warm configuration
        $this->warmConfiguration();
        
        // Warm frequently accessed data
        $this->warmFrequentlyAccessedData();
        
        // Warm reference data
        $this->warmReferenceData();
    }
    
    private function warmUsers()
    {
        // Cache active users
        $activeUsers = User::where('active', true)
            ->limit(1000)
            ->get();
            
        foreach ($activeUsers as $user) {
            $this->cache->tags(['users', "user:{$user->id}"])->put(
                "user:{$user->id}",
                $user,
                3600
            );
        }
        
        // Cache user lists
        $this->cache->tags(['user_lists'])->remember('users.active', 3600, function() {
            return User::where('active', true)->get();
        });
        
        $this->cache->tags(['user_lists'])->remember('users.recent', 1800, function() {
            return User::orderBy('created_at', 'desc')
                ->limit(100)
                ->get();
        });
    }
    
    private function warmConfiguration()
    {
        // Cache application configuration
        $config = [
            'app_name' => config('app.name'),
            'app_debug' => config('app.debug'),
            'app_url' => config('app.url'),
            'mail_driver' => config('mail.driver'),
            'cache_default' => config('cache.default'),
            'session_driver' => config('session.driver')
        ];
        
        $this->cache->tags(['config'])->put('app.config', $config, 86400);
    }
    
    private function warmFrequentlyAccessedData()
    {
        // Cache dashboard statistics
        $this->cache->tags(['dashboard'])->remember('stats.users', 3600, function() {
            return [
                'total' => User::count(),
                'active' => User::where('active', true)->count(),
                'today' => User::whereDate('created_at', today())->count(),
                'this_month' => User::whereMonth('created_at', now()->month)->count()
            ];
        });
        
        // Cache recent posts
        $this->cache->tags(['posts'])->remember('posts.recent', 1800, function() {
            return Post::with('author')
                ->where('published', true)
                ->orderBy('created_at', 'desc')
                ->limit(50)
                ->get();
        });
        
        // Cache popular content
        $this->cache->tags(['content'])->remember('content.popular', 3600, function() {
            return Post::where('published', true)
                ->orderBy('views', 'desc')
                ->limit(20)
                ->get();
        });
    }
    
    private function warmReferenceData()
    {
        // Cache countries
        $this->cache->tags(['reference'])->rememberForever('countries', function() {
            return Country::all();
        });
        
        // Cache categories
        $this->cache->tags(['reference'])->rememberForever('categories', function() {
            return Category::all();
        });
        
        // Cache settings
        $this->cache->tags(['settings'])->rememberForever('settings', function() {
            return Setting::pluck('value', 'key');
        });
    }
    
    // Schedule cache warming
    public function scheduleWarming()
    {
        // Warm cache every hour
        schedule()->call(function() {
            $this->warmCache();
        })->hourly();
        
        // Warm critical data every 15 minutes
        schedule()->call(function() {
            $this->warmFrequentlyAccessedData();
        })->everyFifteenMinutes();
        
        // Warm reference data daily
        schedule()->call(function() {
            $this->warmReferenceData();
        })->daily();
    }
}Monitor and optimize cache performance with metrics, profiling, and tuning. Understanding cache performance helps identify bottlenecks and optimization opportunities.
Monitor cache performance and usage.
use Forge\Cache\CacheProfiler;
use Forge\Cache\CacheMetrics;
// Enable profiling
$profiler = new CacheProfiler($cacheManager);
$profiler->enable();
// Get cache metrics
$metrics = new CacheMetrics($cacheManager);
// Hit/miss ratio
$hitRate = $metrics->getHitRate(); // 0.95 (95%)
$missRate = $metrics->getMissRate(); // 0.05 (5%)
// Operation counts
$stats = $metrics->getStats();
echo "Gets: " . $stats['gets'];
echo "Sets: " . $stats['sets'];
echo "Deletes: " . $stats['deletes'];
echo "Hits: " . $stats['hits'];
echo "Misses: " . $stats['misses'];
// Memory usage
$memoryUsage = $metrics->getMemoryUsage();
echo "Used memory: " . $memoryUsage['used'];
echo "Free memory: " . $memoryUsage['free'];
echo "Total memory: " . $memoryUsage['total'];
// Performance metrics
$performance = $metrics->getPerformance();
echo "Average get time: " . $performance['avg_get_time'] . "ms";
echo "Average set time: " . $performance['avg_set_time'] . "ms";
echo "Average delete time: " . $performance['avg_delete_time'] . "ms";
// Top cached keys
$topKeys = $metrics->getTopKeys(10);
foreach ($topKeys as $key => $hits) {
    echo "{$key}: {$hits} hits";
}
// Least used keys
$leastUsed = $metrics->getLeastUsedKeys(10);
// Cache efficiency
$efficiency = $metrics->getEfficiency();
echo "Cache efficiency: " . ($efficiency * 100) . "%";
// Store metrics for analysis
$metrics->recordMetrics([
    'timestamp' => time(),
    'hit_rate' => $hitRate,
    'memory_usage' => $memoryUsage,
    'performance' => $performance
]);Optimize cache performance based on metrics.
class CacheOptimizer
{
    private $cache;
    private $metrics;
    
    public function __construct(CacheManager $cache, CacheMetrics $metrics)
    {
        $this->cache = $cache;
        $this->metrics = $metrics;
    }
    
    public function optimize()
    {
        // Analyze current performance
        $analysis = $this->analyzePerformance();
        
        // Optimize based on findings
        if ($analysis['hit_rate'] < 0.8) {
            $this->optimizeHitRate();
        }
        
        if ($analysis['memory_usage'] > 0.9) {
            $this->optimizeMemoryUsage();
        }
        
        if ($analysis['avg_get_time'] > 50) {
            $this->optimizeGetTime();
        }
        
        // Apply optimizations
        $this->applyOptimizations($analysis);
    }
    
    private function analyzePerformance()
    {
        $hitRate = $this->metrics->getHitRate();
        $memoryUsage = $this->metrics->getMemoryUsage();
        $performance = $this->metrics->getPerformance();
        $topKeys = $this->metrics->getTopKeys(100);
        
        return [
            'hit_rate' => $hitRate,
            'memory_usage' => $memoryUsage['used'] / $memoryUsage['total'],
            'avg_get_time' => $performance['avg_get_time'],
            'avg_set_time' => $performance['avg_set_time'],
            'top_keys' => $topKeys,
            'total_keys' => count($topKeys)
        ];
    }
    
    private function optimizeHitRate()
    {
        // Increase TTL for frequently accessed items
        $topKeys = $this->metrics->getTopKeys(50);
        
        foreach ($topKeys as $key => $hits) {
            if ($hits > 100) {
                // Get current value and extend TTL
                $value = $this->cache->get($key);
                if ($value !== null) {
                    $this->cache->put($key, $value, 7200); // Extend to 2 hours
                }
            }
        }
        
        // Pre-warm cache with predicted data
        $this->prewarmPredictedData();
    }
    
    private function optimizeMemoryUsage()
    {
        // Remove least used keys
        $leastUsed = $this->metrics->getLeastUsedKeys(100);
        
        foreach ($leastUsed as $key => $hits) {
            if ($hits < 5) {
                $this->cache->forget($key);
            }
        }
        
        // Compress large values
        $this->compressLargeValues();
        
        // Archive old data
        $this->archiveOldData();
    }
    
    private function optimizeGetTime()
    {
        // Switch to faster driver for high-traffic keys
        $highTrafficKeys = $this->metrics->getTopKeys(20);
        
        if (count($highTrafficKeys) > 0) {
            // Consider switching to Redis if using file cache
            $this->upgradeToFasterDriver();
        }
        
        // Optimize network settings
        $this->optimizeNetworkSettings();
    }
    
    private function prewarmPredictedData()
    {
        // Analyze access patterns
        $patterns = $this->analyzeAccessPatterns();
        
        // Pre-warm based on time-based patterns
        $hour = date('H');
        if (isset($patterns['hourly'][$hour])) {
            foreach ($patterns['hourly'][$hour] as $key) {
                if (!$this->cache->has($key)) {
                    $this->warmKey($key);
                }
            }
        }
        
        // Pre-warm based on user behavior
        $this->prewarmUserSpecificData();
    }
    
    private function compressLargeValues()
    {
        // Find large values
        $largeKeys = $this->metrics->getLargeKeys(50);
        
        foreach ($largeKeys as $key => $size) {
            if ($size > 1048576) { // 1MB
                $value = $this->cache->get($key);
                if ($value !== null) {
                    // Compress and re-store
                    $compressed = gzcompress(serialize($value), 9);
                    $this->cache->put($key, $compressed, 3600);
                }
            }
        }
    }
    
    private function upgradeToFasterDriver()
    {
        // This would involve configuration changes
        // to switch from file to Redis, for example
        config(['cache.default' => 'redis']);
        config(['cache.stores.redis.compression' => true]);
    }
    
    // Schedule optimization
    public function scheduleOptimization()
    {
        // Run optimization hourly
        schedule()->call(function() {
            $this->optimize();
        })->hourly();
        
        // Deep analysis daily
        schedule()->call(function() {
            $this->deepAnalysis();
        })->daily();
    }
}Common caching scenarios and implementation patterns for different use cases.
class ApiResponseCache
{
    private $cache;
    
    public function __construct(CacheManager $cache)
    {
        $this->cache = $cache;
    }
    
    public function cacheApiResponse($request, $response, $ttl = 300)
    {
        $key = $this->generateCacheKey($request);
        
        // Add cache headers to response
        $response->headers->set('X-Cache', 'MISS');
        $response->headers->set('Cache-Control', "public, max-age={$ttl}");
        
        // Store in cache
        $this->cache->tags(['api', 'responses'])->put($key, [
            'status' => $response->getStatusCode(),
            'headers' => $response->headers->all(),
            'content' => $response->getContent()
        ], $ttl);
        
        return $response;
    }
    
    public function getCachedResponse($request)
    {
        $key = $this->generateCacheKey($request);
        
        $cached = $this->cache->tags(['api', 'responses'])->get($key);
        
        if ($cached) {
            // Create response from cache
            $response = new Response(
                $cached['content'],
                $cached['status'],
                $cached['headers']
            );
            
            $response->headers->set('X-Cache', 'HIT');
            
            return $response;
        }
        
        return null;
    }
    
    private function generateCacheKey($request)
    {
        $parts = [
            'api',
            $request->method(),
            $request->path(),
            md5(json_encode($request->all())),
            $request->header('Accept-Language', 'en'),
            $request->header('Accept', 'application/json')
        ];
        
        return implode(':', $parts);
    }
    
    // Middleware for API caching
    public function handle($request, $next, $ttl = 300)
    {
        // Check if caching is enabled
        if (!config('api.cache_enabled')) {
            return $next($request);
        }
        
        // Try to get cached response
        $cachedResponse = $this->getCachedResponse($request);
        
        if ($cachedResponse) {
            return $cachedResponse;
        }
        
        // Process request
        $response = $next($request);
        
        // Cache successful responses
        if ($response->isSuccessful()) {
            $this->cacheApiResponse($request, $response, $ttl);
        }
        
        return $response;
    }
}
// Usage in routes
Route::middleware('api.cache:600')->group(function() {
    Route::get('/api/users', 'UserController@index');
    Route::get('/api/posts', 'PostController@index');
    Route::get('/api/categories', 'CategoryController@index');
});class CachedSessionHandler
{
    private $cache;
    private $ttl;
    
    public function __construct(CacheManager $cache, $ttl = 7200)
    {
        $this->cache = $cache;
        $this->ttl = $ttl;
    }
    
    public function read($sessionId)
    {
        $key = "session:{$sessionId}";
        
        $data = $this->cache->get($key);
        
        if ($data !== null) {
            // Extend TTL on access
            $this->cache->expire($key, $this->ttl);
            return $data;
        }
        
        return '';
    }
    
    public function write($sessionId, $data)
    {
        $key = "session:{$sessionId}";
        
        return $this->cache->put($key, $data, $this->ttl);
    }
    
    public function destroy($sessionId)
    {
        $key = "session:{$sessionId}";
        
        return $this->cache->forget($key);
    }
    
    public function gc($maxLifetime)
    {
        // Cache automatically handles expiration
        return true;
    }
    
    // Session data caching with user context
    public function cacheUserSession($userId, $sessionData)
    {
        $key = "user_session:{$userId}";
        
        // Store with user tags for invalidation
        $this->cache->tags(['sessions', "user:{$userId}"])->put($key, [
            'data' => $sessionData,
            'created_at' => now(),
            'last_activity' => now()
        ], $this->ttl);
        
        return true;
    }
    
    public function getUserSessions($userId)
    {
        $key = "user_session:{$userId}";
        
        return $this->cache->tags(['sessions', "user:{$userId}"])->get($key);
    }
    
    public function invalidateUserSessions($userId)
    {
        // Clear all sessions for a user
        $this->cache->tags(['sessions', "user:{$userId}"])->flush();
        
        return true;
    }
    
    // Session locking to prevent race conditions
    public function acquireSessionLock($sessionId, $timeout = 30)
    {
        $lockKey = "session_lock:{$sessionId}";
        
        return $this->cache->lock($lockKey, $timeout)->get();
    }
    
    public function releaseSessionLock($sessionId)
    {
        $lockKey = "session_lock:{$sessionId}";
        
        return $this->cache->lock($lockKey)->release();
    }
}class QueryCache
{
    private $cache;
    
    public function __construct(CacheManager $cache)
    {
        $this->cache = $cache;
    }
    
    public function rememberQuery($query, $ttl = 3600)
    {
        // Generate cache key from query
        $key = $this->generateQueryKey($query);
        
        // Use cache tags based on tables
        $tables = $this->getQueryTables($query);
        $tags = array_merge(['queries'], $tables);
        
        return $this->cache->tags($tags)->remember($key, $ttl, function() use ($query) {
            return $query->get();
        });
    }
    
    public function rememberQueryFirst($query, $ttl = 3600)
    {
        $key = $this->generateQueryKey($query) . ':first';
        $tables = $this->getQueryTables($query);
        $tags = array_merge(['queries'], $tables);
        
        return $this->cache->tags($tags)->remember($key, $ttl, function() use ($query) {
            return $query->first();
        });
    }
    
    public function rememberQueryCount($query, $ttl = 3600)
    {
        $key = $this->generateQueryKey($query) . ':count';
        $tables = $this->getQueryTables($query);
        $tags = array_merge(['queries', 'counts'], $tables);
        
        return $this->cache->tags($tags)->remember($key, $ttl, function() use ($query) {
            return $query->count();
        });
    }
    
    public function flushQueryCache($tables = null)
    {
        if ($tables === null) {
            // Flush all query caches
            $this->cache->tags(['queries'])->flush();
        } else {
            // Flush specific table caches
            $tags = is_array($tables) ? $tables : [$tables];
            $this->cache->tags($tags)->flush();
        }
        
        return true;
    }
    
    private function generateQueryKey($query)
    {
        $sql = $query->toSql();
        $bindings = $query->getBindings();
        
        return 'query:' . md5($sql . serialize($bindings));
    }
    
    private function getQueryTables($query)
    {
        // Extract table names from query
        $sql = $query->toSql();
        preg_match_all('/FROM\s+`?(\w+)`?/', $sql, $matches);
        
        return $matches[1] ?? [];
    }
    
    // Model trait for caching
    public function cachedScope($query, $ttl = 3600)
    {
        return $this->rememberQuery($query, $ttl);
    }
    
    public function cachedRelation($relation, $ttl = 3600)
    {
        $key = "model:{$this->getTable()}:{$this->id}:relation:{$relation}";
        
        return $this->cache->tags(['models', $this->getTable()])->remember($key, $ttl, function() use ($relation) {
            return $this->$relation;
        });
    }
}
// Usage in models
trait Cacheable
{
    public function scopeCached($query, $ttl = 3600)
    {
        $cache = Container::getInstance()->make('cache');
        $queryCache = new QueryCache($cache);
        
        return $queryCache->rememberQuery($query, $ttl);
    }
    
    public function cachedRelation($relation, $ttl = 3600)
    {
        $cache = Container::getInstance()->make('cache');
        $key = "model:{$this->getTable()}:{$this->id}:relation:{$relation}";
        
        return $cache->tags(['models', $this->getTable()])->remember($key, $ttl, function() use ($relation) {
            return $this->$relation;
        });
    }
    
    public function clearCache()
    {
        $cache = Container::getInstance()->make('cache');
        
        // Clear model cache
        $cache->tags(['models', $this->getTable()])->flush();
        
        // Clear specific instance
        $cache->forget("model:{$this->getTable()}:{$this->id}");
        
        return true;
    }
}
// Usage
class User extends Model
{
    use Cacheable;
    
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}
// In controllers
$users = User::cached(3600)->get();
$posts = $user->cachedRelation('posts', 1800);Recommended patterns and guidelines for working with the caching system.