Getting Started

Drop-in replacement for Laravel's Cache facade. SmartCache adds automatic compression, chunking, and cost-aware eviction to any Laravel cache driver. It implements Illuminate\Contracts\Cache\Repository and PSR-16 SimpleCache — your existing code works unchanged.

What is SmartCache?

SmartCache wraps Laravel's caching layer with transparent optimizations while preserving full API compatibility:

📦 Intelligent Compression

Automatic gzip compression for large data — significant size reduction with zero code changes.

🧩 Smart Chunking

Breaks large arrays/objects into manageable pieces for better performance.

🔒 Atomic Locks

Prevent cache stampede and race conditions with distributed locking.

⚡ Cache Memoization

In-memory caching eliminates repeated lookups within a request or job.

🎯 Adaptive Compression

Auto-optimize compression levels based on data characteristics.

💾 Lazy Loading

On-demand chunk loading keeps memory usage low for large datasets.

📡 Cache Events

Monitor and react to cache operations in real-time.

🔄 Zero Breaking Changes

Use exactly like Laravel's Cache facade with automatic optimizations.

🧬 Write Deduplication

Skips redundant writes when content is unchanged — saves I/O for frequently refreshed data.

🩹 Self-Healing Cache

Corrupted entries are auto-evicted and transparently regenerated on the next read.

🎯 Conditional Caching

Cache only when a condition is met — filter out empty or invalid responses with rememberIf().

🔐 Encryption

Automatically encrypt sensitive cached data with pattern matching.

📁 Namespacing

Group cache keys by namespace for better organization and bulk operations.

⏱️ TTL Jitter

Prevent thundering herd with random TTL variation.

🔌 Circuit Breaker

Protect your app from cache backend failures with automatic fallbacks.

Quick Start

1 Install the package:
composer require iazaran/smart-cache
2 Start using it immediately:
use SmartCache\Facades\SmartCache;

// Works exactly like Laravel Cache
SmartCache::put('users', $users, 3600);
$users = SmartCache::get('users');
SmartCache works out-of-the-box with sensible defaults. Data is automatically compressed and optimized when beneficial.

Scales With Your Application

  • Drop-in: Install and benefit immediately — no code changes required
  • Advanced patterns: SWR, stampede protection, dependency-based invalidation
  • Observability: Real-time monitoring, cost-aware eviction, performance analysis
  • Enterprise-ready: Circuit breakers, encryption at rest, dashboards, HTTP management APIs

📦 Installation

Requirements

  • PHP 8.1 or higher
  • Laravel 8.0 - 12.x (fully tested on Laravel 8, 9, 10, 11, and 12)
  • Any Laravel-supported cache driver (Redis, File, Database, Array, Memcached)
Laravel 8–12: All features are tested and supported across every major Laravel release.

Installation Steps

1 Install via Composer:
composer require iazaran/smart-cache

Configuration (Optional)

SmartCache works out-of-the-box with sensible defaults. For advanced customization:

1 Publish the configuration file:
php artisan vendor:publish --tag=smart-cache-config
2 Configure in config/smart-cache.php:
 [
        'compression' => 1024 * 50, // 50KB - compress data larger than this
        'chunking' => 1024 * 100,   // 100KB - chunk arrays larger than this
    ],

    /*
    |--------------------------------------------------------------------------
    | Strategies
    |--------------------------------------------------------------------------
    |
    | Configure which optimization strategies are enabled and their options.
    |
    */
    'strategies' => [
        'compression' => [
            'enabled' => true,
            'level' => 6, // 0-9 (higher = better compression but slower)
        ],
        'chunking' => [
            'enabled' => true,
            'chunk_size' => 1000, // Items per chunk for arrays/collections
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Performance Monitoring
    |--------------------------------------------------------------------------
    |
    | Enable performance monitoring to track cache hit/miss ratios,
    | optimization impact, and operation durations.
    |
    */
    'monitoring' => [
        'enabled' => true,
        'metrics_ttl' => 3600, // How long to keep metrics in cache (seconds)
        'recent_entries_limit' => 100, // Number of recent operations to track
    ],

    /*
    |--------------------------------------------------------------------------
    | Performance Warnings
    |--------------------------------------------------------------------------
    |
    | Configure thresholds for performance warnings and recommendations.
    |
    */
    'warnings' => [
        'hit_ratio_threshold' => 70, // Warn if hit ratio below this percentage
        'optimization_ratio_threshold' => 20, // Warn if optimization usage below this
        'slow_write_threshold' => 0.1, // Warn if writes slower than this (seconds)
    ],

    /*
    |--------------------------------------------------------------------------
    | Cache Drivers
    |--------------------------------------------------------------------------
    |
    | Configure which cache drivers should use which optimization strategies.
    | Set to null to use the global strategies configuration.
    |
    */
    'drivers' => [
        'redis' => null, // Use global settings
        'file' => [
            'compression' => true,
            'chunking' => true,
        ],
        'memcached' => [
            'compression' => false, // Memcached has its own compression
            'chunking' => true,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Fallback
    |--------------------------------------------------------------------------
    |
    | Configure fallback behavior if optimizations fail or are incompatible.
    |
    */
    'fallback' => [
        'enabled' => true,
        'log_errors' => true,
    ],
];

Service Provider

SmartCache automatically registers its service provider. No additional configuration is needed for Laravel 8+.

💻 Basic Usage

Familiar Laravel API

SmartCache works exactly like Laravel's built-in Cache facade. Your existing code works unchanged:

use SmartCache\Facades\SmartCache;

// Basic caching (just like Laravel Cache)
SmartCache::put('user_data', $userData, 3600);
$userData = SmartCache::get('user_data');

// Helper function (just like cache() helper)
smart_cache(['products' => $products], 3600);
$products = smart_cache('products');

// Remember pattern (just like Cache::remember)
$users = SmartCache::remember('users', 3600, function() {
    return User::all();
});

// Check if key exists
if (SmartCache::has('users')) {
    $users = SmartCache::get('users');
}

// Forget a key
SmartCache::forget('users');

// Clear all cache
SmartCache::flush();

Using Different Cache Drivers

Use different cache drivers while maintaining all SmartCache optimizations:

// Use Redis with all SmartCache optimizations (compression, chunking, etc.)
SmartCache::store('redis')->put('key', $value, 3600);
SmartCache::store('redis')->get('key');

// Use Memcached with optimizations
SmartCache::store('memcached')->remember('users', 3600, fn() => User::all());

// Use file cache with optimizations
SmartCache::store('file')->put('config', $config, 86400);

// Chain multiple operations on a specific store
$redisCache = SmartCache::store('redis');
$redisCache->put('users', $users, 3600);
$redisCache->put('products', $products, 3600);

// For raw access to Laravel's cache (bypasses SmartCache optimizations)
SmartCache::repository('redis')->put('key', $value, 3600);
Note: The store() method returns a SmartCache instance, so all optimization strategies (compression, chunking, encryption, etc.) continue to work. Use repository() if you need direct access to Laravel's cache without SmartCache optimizations.
Full Laravel Compatibility: SmartCache implements Laravel's Illuminate\Contracts\Cache\Repository interface, so it works seamlessly with any code that type-hints Repository. The store() method returns a SmartCache instance that is also a valid Repository, ensuring zero breaking changes when migrating from Laravel's Cache facade.

Automatic Optimization

SmartCache automatically optimizes your data when beneficial:

// Large array - automatically chunked
$largeArray = range(1, 10000);
SmartCache::put('large_data', $largeArray, 3600);
// Data is automatically chunked for better performance

// Large string - automatically compressed
$largeString = str_repeat('Hello World! ', 1000);
SmartCache::put('large_text', $largeString, 3600);
// Data is automatically compressed to save space

Cache Tags

Group related cache entries for easy management:

// Store with tags
SmartCache::tags(['users', 'profiles'])->put('user_1', $user1, 3600);
SmartCache::tags(['users', 'profiles'])->put('user_2', $user2, 3600);

// Clear all cache with specific tags
SmartCache::tags(['users'])->flush(); // Clears both user_1 and user_2

// Clear cache with multiple tags
SmartCache::tags(['users', 'profiles'])->flush();

Cache Locking

Prevent cache stampede with atomic locks:

$lock = SmartCache::lock('expensive_operation', 10);

if ($lock->get()) {
    try {
        // Perform expensive operation
        $result = expensiveOperation();
        SmartCache::put('expensive_result', $result, 3600);
    } finally {
        $lock->release();
    }
} else {
    // Wait for the lock to be released
    $result = SmartCache::get('expensive_result');
}

⚡ Optimization Features

Intelligent Compression

SmartCache automatically compresses large data to reduce storage requirements:

// Large data automatically compressed
$largeData = [
    'products' => Product::with('images', 'reviews')->get(),
    'categories' => Category::with('children')->get(),
    'settings' => Setting::all()
];

SmartCache::put('catalog_data', $largeData, 3600);
// Automatically compressed with gzip

Smart Chunking

Large arrays and objects are automatically chunked for better performance:

// Large array automatically chunked
$users = User::with('profile', 'posts')->get(); // 10,000+ records
SmartCache::put('all_users', $users, 3600);
// Automatically split into manageable chunks

Strategy Selection

SmartCache automatically chooses the best optimization strategy:

Data Type Size Strategy Applied Benefit
Large Arrays (5000+ items) Any Chunking Better memory usage, faster access
Text/Strings >50KB Compression Significant size reduction
Mixed Objects >50KB Compression Optimal serialization
API Responses >100KB Chunking + Compression Best performance
Small Data <50KB None Fastest performance

🎯 Adaptive Compression

Auto-optimize compression levels based on data characteristics:

// Enable adaptive compression
config(['smart-cache.strategies.compression.mode' => 'adaptive']);

// Automatically selects optimal compression level:
// - Hot data (frequently accessed) = level 3-4 (faster)
// - Cold data (rarely accessed) = level 7-9 (smaller)
// - Based on compressibility analysis

SmartCache::put('hot_data', $frequentlyAccessed, 3600);
SmartCache::put('cold_data', $rarelyAccessed, 3600);

💾 Lazy Loading

Load large datasets on-demand, keeping only the active chunk in memory:

// Enable lazy loading
config(['smart-cache.strategies.chunking.lazy_loading' => true]);

// Returns LazyChunkedCollection - loads chunks on-demand
$largeDataset = SmartCache::get('100k_records');

foreach ($largeDataset as $record) {
    processRecord($record);
    // Only 3 chunks in memory at once
}

🧠 Smart Serialization

Auto-select best serialization method:

// Automatically chooses:
// - JSON for simple arrays (fastest)
// - igbinary for complex data (if available)
// - PHP serialize as fallback

SmartCache::put('data', $value, 3600);
// Best method selected automatically

📏 Smart Chunk Sizing

Auto-calculate optimal chunk sizes based on cache driver:

// Enable smart chunk sizing
config(['smart-cache.strategies.chunking.smart_sizing' => true]);

// Automatically calculates optimal chunk size based on:
// - Cache driver limits (Redis: 512MB, Memcached: 1MB)
// - Data structure complexity
// - Serialization overhead

SmartCache::put('large_array', $data, 3600);
// Optimal chunk size calculated automatically

Configuration Options

// config/smart-cache.php
return [
    'thresholds' => [
        'compression' => 1024 * 50, // 50KB
        'chunking' => 1024 * 100,   // 100KB
    ],

    'strategies' => [
        'compression' => [
            'enabled' => true,
            'mode' => 'fixed',       // 'fixed' or 'adaptive'
            'level' => 6,            // 1-9 (higher = better compression)
        ],
        'chunking' => [
            'enabled' => true,
            'chunk_size' => 1000,    // Items per chunk
            'lazy_loading' => false, // Enable for memory savings
            'smart_sizing' => false, // Auto-calculate chunk size
        ],
    ],

    'events' => [
        'enabled' => false,          // Enable for monitoring
    ],

    'monitoring' => [
        'enabled' => true,
        'metrics_ttl' => 3600,
    ],
];

What to Expect

Typical improvements depend on your data shapes and access patterns. Compression is most effective on large text and repetitive structures; chunking benefits datasets that exceed driver size limits. Enable monitoring to measure the actual impact in your environment.

🌊 SWR Patterns (Laravel 12+)

Note: SWR patterns require Laravel 12 or higher. For older versions, use the standard caching methods.

What is SWR?

SWR (Stale-While-Revalidate) is a caching strategy that serves stale data immediately while refreshing it in the background. This provides:

  • Instant responses - Users see data immediately
  • 🔄 Fresh data - Background updates ensure data stays current
  • 🚫 No cache stampede - Prevents multiple simultaneous requests

Basic SWR Usage

// SWR: Serve stale data while refreshing in background
$apiData = SmartCache::swr('github_repos', function() {
    return Http::get('https://api.github.com/user/repos')->json();
}, 300, 900); // 5min fresh, 15min stale

Extended Stale Serving

For slowly changing data, serve stale data for extended periods:

// Extended stale serving for site configuration
$siteConfig = SmartCache::stale('site_config', function() {
    return Config::fromDatabase();
}, 3600, 86400); // 1hour fresh, 24hour stale

Refresh-Ahead Caching

Proactively refresh cache before expiration:

// Refresh-ahead for expensive computations
$analytics = SmartCache::refreshAhead('daily_analytics', function() {
    return Analytics::generateReport();
}, 1800, 300); // 30min TTL, 5min refresh window

Queue-Based Background Refresh

Return stale data immediately and refresh asynchronously via a queued job:

// Returns stale data instantly, dispatches a background job to refresh
$data = SmartCache::asyncSwr('dashboard_stats', function() {
    return Stats::generate();
}, 300, 900, 'cache-refresh'); // 5min fresh, 15min stale, dispatched to 'cache-refresh' queue

Real-World Examples

API Gateway Cache

class ApiController
{
    public function getProducts()
    {
        return SmartCache::swr('api_products', function() {
            return Product::with('images', 'reviews')->get();
        }, 300, 900); // 5min fresh, 15min stale
    }
    
    public function getUserProfile($userId)
    {
        return SmartCache::stale("user_profile_{$userId}", function() use ($userId) {
            return User::with('profile', 'settings')->find($userId);
        }, 1800, 3600); // 30min fresh, 1hour stale
    }
}

E-commerce Product Recommendations

class RecommendationService
{
    public function getRecommendations($userId)
    {
        return SmartCache::refreshAhead(
            "recommendations_{$userId}",
            function() use ($userId) {
                return $this->aiEngine->generateRecommendations($userId);
            },
            3600, 600 // 1hour TTL, 10min refresh window
        );
    }
}

📊 Performance Monitoring

Real-Time Metrics

Get comprehensive performance metrics about your cache usage:

// Get all performance metrics
$metrics = SmartCache::getPerformanceMetrics();

/*
Returns:
[
    'cache_efficiency' => [
        'hit_ratio' => 0.943,
        'miss_ratio' => 0.057,
        'total_requests' => 1000
    ],
    'optimization_impact' => [
        'compression_savings' => 0.68,
        'chunking_benefits' => 0.23,
        'total_size_reduction' => 0.72
    ],
    'operation_timing' => [
        'average_get_time' => 0.023,
        'average_put_time' => 0.045,
        'total_operations' => 5000
    ]
]
*/

Health Analysis

Get automated analysis and recommendations:

// Automated performance analysis
$analysis = SmartCache::analyzePerformance();

/*
Returns:
[
    'overall_health' => 'good', // good, warning, critical
    'recommendations' => [
        'Consider increasing cache TTL for frequently accessed data',
        'Enable compression for large text data'
    ],
    'issues' => [],
    'score' => 85
]
*/

HTTP Command Execution

Manage cache via HTTP API (perfect for web-based admin panels):

// Get available commands
$commands = SmartCache::getAvailableCommands();

// Execute commands via HTTP
$status = SmartCache::executeCommand('status');
$clearResult = SmartCache::executeCommand('clear');
$specificClear = SmartCache::executeCommand('clear', [
    'key' => 'expensive_computation',
    'force' => true
]);

CLI Commands

# Quick status overview
php artisan smart-cache:status

# Detailed analysis with recommendations
php artisan smart-cache:status --force

# Clear all SmartCache managed keys
php artisan smart-cache:clear

# Clear specific key
php artisan smart-cache:clear expensive_api_call

# Force clear any cache key
php artisan smart-cache:clear --force

🔧 Advanced Features

All advanced features are opt-in and backwards-compatible: Atomic Locks, Memoization, Events, Adaptive Compression, Lazy Loading, Smart Invalidation, and more.

🔒 Atomic Locks

Prevent multiple processes from regenerating expensive cache simultaneously (prevents race conditions):

// Prevent cache stampede with distributed locks
$lock = SmartCache::lock('expensive_operation', 10);

if ($lock->get()) {
    // Only one process executes this
    $data = expensiveApiCall();
    SmartCache::put('api_data', $data, 3600);
    $lock->release();
}

// Or use callback pattern for automatic release
SmartCache::lock('regenerate_cache', 30)->get(function() {
    return regenerateExpensiveData();
});

⚡ Cache Memoization

Hold retrieved values in memory for the duration of a request or job, eliminating repeated cache lookups:

// Get memoized cache instance
$memo = SmartCache::memo();

// First call hits cache, subsequent calls are instant (from memory)
$users = $memo->remember('users', 3600, fn() => User::all());
$users = $memo->get('users'); // From memory — no cache round-trip
$users = $memo->get('users'); // Still from memory

// Perfect for loops and repeated access
foreach ($products as $product) {
    $category = $memo->get("category_{$product->category_id}");
    // First access hits cache, subsequent accesses are instant
}

// Get memoization statistics
$stats = $memo->getMemoizationStats();
// Returns: memoized_count, missing_count, total_memory

📡 Cache Events

Monitor and react to cache operations in real-time:

// Enable events in config
config(['smart-cache.events.enabled' => true]);

// Listen to cache operations
use SmartCache\Events\{CacheHit, CacheMissed, KeyWritten, KeyForgotten, OptimizationApplied};

Event::listen(CacheHit::class, function ($event) {
    Log::info("Cache hit: {$event->key}", ['tags' => $event->tags]);
});

Event::listen(CacheMissed::class, function ($event) {
    Log::warning("Cache miss: {$event->key}");
});

Event::listen(OptimizationApplied::class, function ($event) {
    Log::info("Optimized {$event->key}: {$event->strategy} - {$event->ratio}% reduction");
});
Note: Events are disabled by default for performance. Enable only when you need monitoring.

🔢 Batch Operations

Optimize multiple cache operations:

// Retrieve multiple keys at once
$values = SmartCache::many(['key1', 'key2', 'key3']);

// Store multiple keys at once
SmartCache::putMany([
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3',
], 3600);

// Delete multiple keys at once
SmartCache::deleteMultiple(['key1', 'key2', 'key3']);

🎯 Adaptive Compression

Auto-optimize compression levels based on data characteristics:

// Enable adaptive compression in config
config(['smart-cache.strategies.compression.mode' => 'adaptive']);

// Automatically selects optimal compression level based on:
// - Data compressibility (sample-based analysis)
// - Access frequency (hot data = faster compression)
// - Data size (larger data = higher compression)

SmartCache::put('hot_data', $frequentlyAccessed, 3600);  // Uses level 3-4 (faster)
SmartCache::put('cold_data', $rarelyAccessed, 3600);     // Uses level 7-9 (smaller)

// Get compression statistics
$stats = SmartCache::getCompressionStats($optimizedValue);
// Returns: level, original_size, compressed_size, ratio, savings_bytes, savings_percent

💾 Lazy Loading

Load large datasets on-demand, keeping only the active chunk in memory:

// Enable lazy loading in config
config(['smart-cache.strategies.chunking.lazy_loading' => true]);

// Large datasets return LazyChunkedCollection
$largeDataset = SmartCache::get('100k_records');

// Chunks loaded on-demand (max 3 in memory at once)
foreach ($largeDataset as $record) {
    processRecord($record);
    // Only loads chunks as needed
}

// Access specific items
$item = $largeDataset[50000]; // Only loads the chunk containing this item

// Collection methods work too
$filtered = $largeDataset->filter(fn($item) => $item->active);
$mapped = $largeDataset->map(fn($item) => $item->name);

🧠 Smart Serialization

Auto-select best serialization method for optimal performance:

// Automatically chooses best method:
// - JSON for simple arrays (fastest, most compact)
// - igbinary for complex data (if available)
// - PHP serialize as fallback

SmartCache::put('simple_data', ['key' => 'value'], 3600);  // Uses JSON
SmartCache::put('complex_data', $objectGraph, 3600);       // Uses igbinary/PHP

// Get serialization statistics
$stats = SmartCache::getSerializationStats($optimizedValue);
// Returns: method, original_size, serialized_size, ratio

Smart Cache Invalidation

Dependency Tracking

Create cache hierarchies where invalidating a parent clears all children:

// Create cache dependencies
SmartCache::dependsOn('user_posts', 'user_profile');
SmartCache::dependsOn('user_stats', 'user_profile');

// Invalidate parent - children cleared automatically
SmartCache::invalidate('user_profile');
// This will also clear 'user_posts' and 'user_stats'

Pattern-Based Invalidation

Clear cache entries using wildcards and regex patterns:

// Pattern-based clearing
SmartCache::flushPatterns([
    'user_*',           // All user keys
    'api_v2_*',         // All API v2 cache
    '/product_\d+/'     // Regex: product_123, product_456
]);

Model Auto-Invalidation

Automatically clear cache when Eloquent models change:

use SmartCache\Traits\CacheInvalidation;

class User extends Model
{
    use CacheInvalidation;
    
    public function getCacheKeysToInvalidate(): array
    {
        return [
            "user_{$this->id}_profile",
            "user_{$this->id}_posts",
            'users_list_*'
        ];
    }
}

// Cache automatically cleared when user changes!
$user = User::find(1);
$user->update(['name' => 'New Name']); // Cache cleared automatically

Custom Optimization Strategies

Create custom optimization strategies for your specific needs:

use SmartCache\Contracts\OptimizationStrategy;

class JsonCompressionStrategy implements OptimizationStrategy
{
    public function shouldApply(mixed $value, array $context = []): bool
    {
        return is_array($value) && 
               json_encode($value, JSON_UNESCAPED_UNICODE) !== false &&
               strlen(json_encode($value)) > 10240; // 10KB threshold
    }
    
    public function optimize(mixed $value, array $context = []): mixed
    {
        $json = json_encode($value, JSON_UNESCAPED_UNICODE);
        return [
            '_sc_json_compressed' => true,
            'data' => gzcompress($json, 9)
        ];
    }
    
    public function restore(mixed $value, array $context = []): mixed
    {
        if (is_array($value) && ($value['_sc_json_compressed'] ?? false)) {
            return json_decode(gzuncompress($value['data']), true);
        }
        return $value;
    }
    
    public function getIdentifier(): string
    {
        return 'json_compression';
    }
}

// Register your custom strategy
SmartCache::addStrategy(new JsonCompressionStrategy());

✨ Extended Features

All extended features are opt-in and backwards-compatible: Write Deduplication, Self-Healing Cache, Conditional Caching, Cost-Aware Caching, Encryption at Rest, Namespacing, TTL Jitter, Circuit Breaker, Rate Limiting, Cache Warming, and more.

🔐 Encryption Strategy

Encrypt sensitive cached data automatically:

// Configure encryption in config/smart-cache.php
'encryption' => [
    'enabled' => true,
    'keys' => ['user_*', 'payment_*'],     // Keys to encrypt
    'patterns' => ['/secret_.*/'],          // Regex patterns
],

// Data matching patterns is automatically encrypted
SmartCache::put('user_123_data', $sensitiveData, 3600);
// Automatically encrypted at rest

// Decryption is automatic on retrieval
$data = SmartCache::get('user_123_data');
// Returns decrypted data

📁 Cache Namespacing

Group cache keys by namespace for better organization:

// Set active namespace
SmartCache::namespace('api_v2');

// All operations now use this namespace
SmartCache::put('users', $users, 3600);  // Actually stores 'api_v2:users'
SmartCache::get('users');                 // Gets 'api_v2:users'

// Flush entire namespace
SmartCache::flushNamespace('api_v2');

// Get all keys in namespace
$keys = SmartCache::getNamespaceKeys('api_v2');

// Disable namespace temporarily
SmartCache::withoutNamespace()->put('global_key', $value, 3600);

⏱️ TTL Jitter

Prevent thundering herd by adding random variation to TTL:

// Enable jitter globally in config
'jitter' => [
    'enabled' => true,
    'percentage' => 0.1,  // 10% variation
],

// Or enable per-operation
SmartCache::withJitter(0.15)->put('key', $value, 3600);
// TTL will be 3060-3540 seconds (±15%)

// Use jitter-specific methods
SmartCache::putWithJitter('key', $value, 3600, 0.2);
SmartCache::rememberWithJitter('key', 3600, fn() => $value, 0.1);
Why Jitter? When many cache entries expire at the same time, they all try to regenerate simultaneously (thundering herd). Jitter spreads out expirations to prevent this.

🔌 Circuit Breaker

Protect your application from cache backend failures:

// Configure circuit breaker
'circuit_breaker' => [
    'enabled' => true,
    'failure_threshold' => 5,   // Open after 5 failures
    'success_threshold' => 2,   // Close after 2 successes
    'timeout' => 30,            // Try again after 30 seconds
],

// Check if cache is available
if (SmartCache::isAvailable()) {
    $data = SmartCache::get('key');
} else {
    $data = $this->fallbackSource();
}

// Use fallback automatically
$data = SmartCache::withFallback(
    fn() => SmartCache::get('key'),
    fn() => $this->fallbackSource()
);

// Get circuit breaker statistics
$stats = SmartCache::getCircuitBreakerStats();
// Returns: state, failures, successes, last_failure_time

🚦 Rate Limiting & Stampede Protection

Prevent cache stampede with probabilistic early expiration:

// Throttle cache regeneration
SmartCache::throttle('expensive_key', 10, 60, function() {
    return expensiveOperation();
}); // Max 10 regenerations per 60 seconds

// Stampede protection with XFetch algorithm
$data = SmartCache::rememberWithStampedeProtection(
    'popular_key',
    3600,
    fn() => expensiveQuery(),
    1.0  // Beta factor (higher = earlier refresh)
);

// Configure rate limiter
'rate_limiter' => [
    'enabled' => true,
    'default_limit' => 100,
    'window' => 60,
],

🔥 Cache Warming

Pre-populate cache with frequently accessed data:

// Create a cache warmer
use SmartCache\Contracts\CacheWarmer;

class ProductCacheWarmer implements CacheWarmer
{
    public function warm(): void
    {
        $products = Product::with('images')->get();
        SmartCache::put('all_products', $products, 3600);
    }

    public function getKeys(): array
    {
        return ['all_products'];
    }
}

// Register in service provider
$this->app->tag([ProductCacheWarmer::class], 'cache.warmers');

// Run cache warming command
php artisan smart-cache:warm

// Or warm specific keys
php artisan smart-cache:warm --keys=all_products,categories

🧹 Orphan Chunk Cleanup

Automatically clean up orphaned chunks from expired data:

// Run cleanup command
php artisan smart-cache:cleanup-chunks

// Schedule automatic cleanup
// In app/Console/Kernel.php
$schedule->command('smart-cache:cleanup-chunks')->daily();

// Cleanup is also triggered automatically when:
// - A chunked key is forgotten
// - A chunked key expires and is accessed

📊 Cache Statistics Dashboard

Visual dashboard for monitoring cache performance:

// Enable dashboard in config
'dashboard' => [
    'enabled' => true,
    'prefix' => 'smart-cache',
    'middleware' => ['web', 'auth'],
],

// Access dashboard at:
// GET /smart-cache/dashboard

// JSON API endpoints:
// GET /smart-cache/stats     - Performance metrics
// GET /smart-cache/health    - Health check
// GET /smart-cache/keys      - Managed keys list

🔄 Background Refresh

Queue-based background cache refresh:

use SmartCache\Jobs\BackgroundCacheRefreshJob;

// Dispatch background refresh
BackgroundCacheRefreshJob::dispatch(
    'expensive_key',
    fn() => expensiveOperation(),
    3600
);

// Or use asyncSwr — returns stale data immediately, refreshes via queue
SmartCache::asyncSwr('key', fn() => $data, 300, 900, 'cache-refresh');

🧠 Cost-Aware Caching

Inspired by the GreedyDual-Size algorithm, every remember() call automatically tracks regeneration cost, access frequency, and data size to compute a value score — letting you make data-driven eviction decisions.

How it works: Each cache entry receives a score calculated as score = (cost × ln(1 + access_count) × decay) / size. Expensive, frequently accessed, small entries score highest. Cheap, rarely used, large entries score lowest.
// Automatic — just use remember() as usual
$report = SmartCache::remember('analytics', 3600, function () {
    return AnalyticsService::generateReport(); // 800ms callback
});

$users = SmartCache::remember('users', 3600, function () {
    return User::all(); // 5ms callback
});

// See which cache entries are most valuable
$report = SmartCache::getCacheValueReport();
// [
//   ['key' => 'analytics', 'cost_ms' => 800, 'access_count' => 47, 'score' => 92.4],
//   ['key' => 'users',     'cost_ms' => 5,   'access_count' => 120, 'score' => 14.1],
// ]

// Get value score for a specific key
$meta = SmartCache::cacheValue('analytics');
// ['cost_ms' => 800, 'access_count' => 47, 'size_bytes' => 4096, 'score' => 92.4]

// When you need to free space, find the least valuable entries
$evictable = SmartCache::suggestEvictions(5);
// Returns the 5 lowest-score keys — safe to remove first
Useful for production monitoring, capacity planning, and intelligent eviction policies — know exactly which keys matter and which waste space.

🧬 Write Deduplication (Cache DNA)

SmartCache hashes every value before writing. When the stored content is identical to what is already cached, the write is skipped entirely — eliminating redundant I/O for frequently refreshed but rarely changing data such as configuration, feature flags, and rate-limit counters.

// Frequent cron refreshes? Only the first write hits the store.
SmartCache::put('app_config', Config::all(), 3600);

// Second call with the same data — no I/O, returns true immediately
SmartCache::put('app_config', Config::all(), 3600);

// When data actually changes, the write proceeds normally
SmartCache::put('app_config', $updatedConfig, 3600); // written
How it works: An MD5 hash of the serialized value is stored alongside each entry as _sc_dna:{key}. On subsequent writes, SmartCache compares the hash — if identical, the write is skipped. Hashes share the same TTL as the data and are cleaned up on forget().
// Enable/disable in config/smart-cache.php
'deduplication' => [
    'enabled' => true,   // enabled by default
],

🎯 Conditional Caching (rememberIf)

Cache values only when a condition is met. The callback always executes, but the result is stored only if the condition returns true. This is useful for filtering out empty, error, or invalid responses from external APIs.

// Only cache non-empty API responses
$data = SmartCache::rememberIf('external_api', 3600,
    fn() => Http::get('https://api.example.com/data')->json(),
    fn($value) => !empty($value) && isset($value['status'])
);

// Only cache results above a minimum size
$report = SmartCache::rememberIf('analytics_report', 7200,
    fn() => AnalyticsService::generate(),
    fn($result) => count($result) > 0
);

// Combined with cost-aware caching — generation cost is still tracked
$users = SmartCache::rememberIf('active_users', 1800,
    fn() => User::where('active', true)->get(),
    fn($users) => $users->isNotEmpty()
);
Unlike wrapping remember() with an if check, rememberIf() integrates with cost tracking and deduplication out of the box.

🩹 Self-Healing Cache

Corrupted or unrestorable cache entries are automatically evicted instead of propagating an exception to the application. Combined with remember() or rememberIf(), the entry is transparently regenerated on the next read — zero downtime, zero manual intervention.

// If 'report' is corrupted, SmartCache evicts it silently
// and the callback regenerates it on the next call
$report = SmartCache::remember('report', 3600, fn() => Analytics::generate());

// Self-healing also cleans up associated DNA hashes
// and logs the eviction for observability:
// "SmartCache self-healing: evicted corrupted key [report]"
// Enable/disable in config/smart-cache.php
'self_healing' => [
    'enabled' => true,   // enabled by default
],
Enterprise use case: In high-availability environments, a single corrupted cache entry can cascade into repeated exceptions. Self-healing ensures the application degrades gracefully, evicts the bad entry, and recovers automatically.

Configuration Reference

// config/smart-cache.php
return [
    // ... existing options ...

    'encryption' => [
        'enabled' => false,
        'keys' => [],
        'patterns' => [],
    ],

    'circuit_breaker' => [
        'enabled' => true,
        'failure_threshold' => 5,
        'success_threshold' => 2,
        'timeout' => 30,
    ],

    'rate_limiter' => [
        'enabled' => true,
        'default_limit' => 100,
        'window' => 60,
    ],

    'jitter' => [
        'enabled' => false,
        'percentage' => 0.1,
    ],

    'cost_aware' => [
        'enabled' => true,              // Toggle cost tracking on/off
        'max_tracked_keys' => 1000,     // Limit metadata memory
        'metadata_ttl' => 86400,        // Metadata persistence (1 day)
    ],

    'deduplication' => [
        'enabled' => true,              // Write deduplication (Cache DNA)
    ],

    'self_healing' => [
        'enabled' => true,              // Auto-evict corrupted entries
    ],

    'dashboard' => [
        'enabled' => false,
        'prefix' => 'smart-cache',
        'middleware' => ['web'],
    ],
];

📚 API Reference

All public methods, parameters, and return types with examples.

🔧 Basic Cache Operations

SmartCache::get()
SmartCache::get(string $key, mixed $default = null): mixed

Retrieve an item from the cache with automatic restoration of optimized data.

$key (string) - The cache key
$default (mixed) - Default value if key doesn't exist
Returns: mixed - The cached value or default
Examples:
$users = SmartCache::get('users', []);
$config = SmartCache::get('app_config', collect());
SmartCache::put()
SmartCache::put(string $key, mixed $value, DateTimeInterface|DateInterval|int|null $ttl = null): bool

Store an item in the cache with automatic optimization (compression/chunking).

$key (string) - The cache key
$value (mixed) - The value to store
$ttl (DateTimeInterface|DateInterval|int|null) - Time to live
Returns: bool - True on success
Examples:
SmartCache::put('users', $users, 3600);
SmartCache::put('config', $config, now()->addHours(2));
SmartCache::remember()
SmartCache::remember(string $key, DateTimeInterface|DateInterval|int|null $ttl, Closure $callback): mixed

Get an item from the cache, or execute the callback and store the result.

$key (string) - The cache key
$ttl (DateTimeInterface|DateInterval|int|null) - Time to live
$callback (Closure) - Function to generate fresh data
Returns: mixed - Cached or fresh data
Example:
$users = SmartCache::remember('users', 3600, function() {
    return User::with('profile')->get();
});
SmartCache::rememberIf()
SmartCache::rememberIf(string $key, mixed $ttl, Closure $callback, callable $condition): mixed

Get an item from the cache, or execute the callback and store the result only if the condition is met. The callback always runs on a cache miss, but the value is persisted only when $condition($value) returns true.

$key (string) - The cache key
$ttl (DateTimeInterface|DateInterval|int|null) - Time to live
$callback (Closure) - Function to generate fresh data
$condition (callable) - Receives the callback result; return true to cache
Returns: mixed - Cached or fresh data (always returns the value, even when not cached)
Example:
$data = SmartCache::rememberIf('api_data', 3600,
    fn() => Http::get('https://api.example.com/data')->json(),
    fn($value) => !empty($value) && isset($value['status'])
);
SmartCache::has()
SmartCache::has(string $key): bool

Determine if an item exists in the cache.

$key (string) - The cache key
Returns: bool - True if exists
Example:
if (SmartCache::has('users')) {
    $users = SmartCache::get('users');
}
SmartCache::forget()
SmartCache::forget(string $key): bool

Remove an item from the cache, including any optimized chunks.

$key (string) - The cache key
Returns: bool - True on success
Example:
SmartCache::forget('users');
SmartCache::store()
SmartCache::store(string|null $name = null): static

Get a SmartCache instance for a specific cache driver. All SmartCache optimizations (compression, chunking, encryption, etc.) are preserved. The returned instance also implements Illuminate\Contracts\Cache\Repository for full Laravel compatibility.

$name (string|null) - The cache store name (redis, file, memcached, etc.)
Returns: static - SmartCache instance configured for the specified store (also implements Repository)
Examples:
// Use Redis with all SmartCache optimizations
SmartCache::store('redis')->put('key', $value, 3600);
SmartCache::store('redis')->get('key');

// Use Memcached with optimizations
SmartCache::store('memcached')->remember('users', 3600, fn() => User::all());

// Chain operations on a specific store
$redisCache = SmartCache::store('redis');
$redisCache->put('users', $users, 3600);
$redisCache->put('products', $products, 3600);

// Works with Repository type hints
function cacheData(\Illuminate\Contracts\Cache\Repository $cache) {
    $cache->put('key', 'value', 3600);
}
cacheData(SmartCache::store('redis')); // ✅ Works
SmartCache::repository()
SmartCache::repository(string|null $name = null): \Illuminate\Contracts\Cache\Repository

Get direct access to Laravel's underlying cache repository. This bypasses all SmartCache optimizations.

$name (string|null) - The cache store name (redis, file, memcached, etc.)
Returns: Repository - Laravel's native cache repository
Examples:
// Direct access to Redis cache (no SmartCache optimizations)
SmartCache::repository('redis')->put('key', $value, 3600);

// Direct access to default cache store
SmartCache::repository()->get('key');
Note: Use repository() only when you need to bypass SmartCache optimizations. For normal usage, prefer store() to maintain all optimization benefits.

🌊 SWR Patterns (Laravel 12+)

SmartCache::swr() Laravel 12+
SmartCache::swr(string $key, Closure $callback, int $ttl = 3600, int $staleTtl = 7200): mixed

Stale-While-Revalidate pattern - serves stale data while refreshing in background.

$key (string) - The cache key
$callback (Closure) - Function to generate fresh data
$ttl (int) - Fresh data TTL in seconds
$staleTtl (int) - Stale data TTL in seconds
Returns: mixed - Fresh or stale data
Example:
$apiData = SmartCache::swr('github_repos', function() {
    return Http::get('https://api.github.com/user/repos')->json();
}, 300, 900); // 5min fresh, 15min stale
SmartCache::stale() Laravel 12+
SmartCache::stale(string $key, Closure $callback, int $ttl = 1800, int $staleTtl = 86400): mixed

Extended stale serving - allows serving stale data for extended periods.

$key (string) - The cache key
$callback (Closure) - Function to generate fresh data
$ttl (int) - Fresh data TTL in seconds
$staleTtl (int) - Stale data TTL in seconds
Returns: mixed - Fresh or stale data
Example:
$siteConfig = SmartCache::stale('site_config', function() {
    return Config::fromDatabase();
}, 3600, 86400); // 1hour fresh, 24hour stale
SmartCache::refreshAhead() Laravel 12+
SmartCache::refreshAhead(string $key, Closure $callback, int $ttl = 3600, int $refreshWindow = 600): mixed

Refresh-ahead pattern - proactively refreshes cache before expiration.

$key (string) - The cache key
$callback (Closure) - Function to generate fresh data
$ttl (int) - Cache TTL in seconds
$refreshWindow (int) - Refresh window in seconds
Returns: mixed - Cached or fresh data
Example:
$analytics = SmartCache::refreshAhead('daily_analytics', function() {
    return Analytics::generateReport();
}, 1800, 300); // 30min TTL, 5min refresh window
SmartCache::asyncSwr() Laravel 12+
SmartCache::asyncSwr(string $key, callable|string $callback, int $ttl = 3600, int $staleTtl = 7200, ?string $queue = null): mixed

Queue-based background SWR — returns stale data immediately and dispatches a queued job to refresh the cache asynchronously.

$key (string) - The cache key
$callback (callable|string) - Function to generate fresh data
$ttl (int) - Fresh TTL in seconds
$staleTtl (int) - Maximum stale time in seconds
$queue (?string) - Queue name for the background refresh job
Returns: mixed - Fresh or stale data
Example:
$data = SmartCache::asyncSwr('dashboard_stats', function() {
    return Stats::generate();
}, 300, 900, 'cache-refresh'); // 5min fresh, 15min stale, queued on 'cache-refresh'

🔗 Cache Invalidation & Dependencies

SmartCache::tags()
SmartCache::tags(string|array $tags): static

Tag cache entries for organized invalidation.

$tags (string|array) - Tag name(s)
Returns: static - Chainable instance
Example:
SmartCache::tags(['users', 'profiles'])->put('user_1', $user1, 3600);
SmartCache::tags('products')->put('product_123', $product, 1800);
SmartCache::flushTags()
SmartCache::flushTags(string|array $tags): bool

Flush all cache entries associated with given tags.

$tags (string|array) - Tag name(s)
Returns: bool - True on success
Example:
SmartCache::flushTags(['users']); // Clear all user-related cache
SmartCache::dependsOn()
SmartCache::dependsOn(string $key, string|array $dependencies): static

Add cache key dependency relationships.

$key (string) - The dependent cache key
$dependencies (string|array) - Parent key(s)
Returns: static - Chainable instance
Example:
SmartCache::dependsOn('user_posts', 'user_profile');
SmartCache::flushPatterns()
SmartCache::flushPatterns(array $patterns): int

Clear cache entries matching wildcard or regex patterns.

$patterns (array) - Array of patterns (wildcards or regex)
Returns: int - Number of keys cleared
Example:
$cleared = SmartCache::flushPatterns([
    'user_*',           // All user keys
    'api_v2_*',         // All API v2 cache
    '/product_\d+/'     // Regex: product_123, product_456
]);

📊 Performance Monitoring

SmartCache::getPerformanceMetrics()
SmartCache::getPerformanceMetrics(): array

Get comprehensive performance metrics about cache usage.

Returns: array - Performance metrics including hit ratios, timing, and optimization impact
Example:
$metrics = SmartCache::getPerformanceMetrics();
/*
Returns:
[
    'cache_efficiency' => [
        'hit_ratio' => 0.943,
        'miss_ratio' => 0.057,
        'total_requests' => 1000
    ],
    'optimization_impact' => [
        'compression_savings' => 0.68,
        'chunking_benefits' => 0.23,
        'total_size_reduction' => 0.72
    ]
]
*/
SmartCache::analyzePerformance()
SmartCache::analyzePerformance(): array

Get automated performance analysis and recommendations.

Returns: array - Analysis with health status, recommendations, and score
Example:
$analysis = SmartCache::analyzePerformance();
/*
Returns:
[
    'overall_health' => 'good', // good, warning, critical
    'recommendations' => [
        'Consider increasing cache TTL for frequently accessed data'
    ],
    'score' => 85
]
*/
SmartCache::executeCommand()
SmartCache::executeCommand(string $command, array $parameters = []): array

Execute cache management commands programmatically.

$command (string) - Command to execute (status, clear, etc.)
$parameters (array) - Command parameters
Returns: array - Command result
Example:
$status = SmartCache::executeCommand('status');
$result = SmartCache::executeCommand('clear', ['key' => 'specific_key']);

🔧 Extended API

SmartCache::lock()
SmartCache::lock(string $name, int $seconds = 0, string|null $owner = null): \Illuminate\Contracts\Cache\Lock

Get a lock instance to prevent cache stampede and race conditions.

$name (string) - Lock name
$seconds (int) - Lock timeout in seconds
$owner (string|null) - Lock owner identifier
Returns: Lock - Lock instance
Example:
$lock = SmartCache::lock('expensive_operation', 10);
if ($lock->get()) {
    $data = expensiveApiCall();
    SmartCache::put('api_data', $data, 3600);
    $lock->release();
}
SmartCache::memo()
SmartCache::memo(): \SmartCache\Drivers\MemoizedCacheDriver

Get a memoized cache instance that holds values in memory for the current request.

Returns: MemoizedCacheDriver - Memoized cache instance
Example:
$memo = SmartCache::memo();
$users = $memo->remember('users', 3600, fn() => User::all());
$users = $memo->get('users'); // From memory — no cache round-trip
SmartCache::many()
SmartCache::many(array $keys): array

Retrieve multiple cache keys at once.

$keys (array) - Array of cache keys
Returns: array - Associative array of key => value pairs
Example:
$values = SmartCache::many(['key1', 'key2', 'key3']);
SmartCache::putMany()
SmartCache::putMany(array $values, DateTimeInterface|DateInterval|int|null $ttl = null): bool

Store multiple cache keys at once.

$values (array) - Associative array of key => value pairs
$ttl (int|null) - Time to live in seconds
Returns: bool - True on success
Example:
SmartCache::putMany([
    'key1' => 'value1',
    'key2' => 'value2',
], 3600);
SmartCache::deleteMultiple()
SmartCache::deleteMultiple(array $keys): bool

Delete multiple cache keys at once.

$keys (array) - Array of cache keys
Returns: bool - True on success
Example:
SmartCache::deleteMultiple(['key1', 'key2', 'key3']);
SmartCache::getCompressionStats()
SmartCache::getCompressionStats(mixed $optimizedValue): array

Get compression statistics for optimized data.

$optimizedValue (mixed) - Optimized value from cache
Returns: array - Compression stats (level, sizes, ratio, savings)
Example:
$optimized = SmartCache::optimize($data);
$stats = SmartCache::getCompressionStats($optimized);
// Returns: level, original_size, compressed_size, ratio, savings_bytes, savings_percent
SmartCache::getSerializationStats()
SmartCache::getSerializationStats(mixed $optimizedValue): array

Get serialization statistics for optimized data.

$optimizedValue (mixed) - Optimized value from cache
Returns: array - Serialization stats (method, sizes, ratio)
Example:
$optimized = SmartCache::optimize($data);
$stats = SmartCache::getSerializationStats($optimized);
// Returns: method, original_size, serialized_size, ratio

✨ Resilience & Organization API

SmartCache::namespace()
SmartCache::namespace(string $namespace): static

Set the active namespace for cache operations.

$namespace (string) - Namespace prefix
Returns: static - Chainable instance
Example:
SmartCache::namespace('api_v2')->put('users', $users, 3600);
// Stores as 'api_v2:users'
SmartCache::flushNamespace()
SmartCache::flushNamespace(string $namespace): int

Flush all cache entries in a namespace.

$namespace (string) - Namespace to flush
Returns: int - Number of keys flushed
Example:
$count = SmartCache::flushNamespace('api_v2');
// Clears all keys prefixed with 'api_v2:'
SmartCache::withJitter()
SmartCache::withJitter(float $percentage = 0.1): static

Enable TTL jitter for subsequent operations.

$percentage (float) - Jitter percentage (0.1 = 10%)
Returns: static - Chainable instance
Example:
SmartCache::withJitter(0.15)->put('key', $value, 3600);
// TTL will be 3060-3540 seconds (±15%)
SmartCache::isAvailable()
SmartCache::isAvailable(): bool

Check if cache backend is available (circuit breaker).

Returns: bool - True if cache is available
Example:
if (SmartCache::isAvailable()) {
    $data = SmartCache::get('key');
} else {
    $data = $this->fallbackSource();
}
SmartCache::withFallback()
SmartCache::withFallback(callable $operation, callable $fallback): mixed

Execute cache operation with automatic fallback on failure.

$operation (callable) - Primary cache operation
$fallback (callable) - Fallback if cache fails
Returns: mixed - Result from operation or fallback
Example:
$data = SmartCache::withFallback(
    fn() => SmartCache::get('key'),
    fn() => $this->database->get('key')
);
SmartCache::throttle()
SmartCache::throttle(string $key, int $maxAttempts, int $decaySeconds, callable $callback): mixed

Rate-limit cache regeneration to prevent stampede.

$key (string) - Cache key
$maxAttempts (int) - Max regenerations allowed
$decaySeconds (int) - Time window in seconds
$callback (callable) - Value generator
Returns: mixed - Cached or generated value
Example:
$data = SmartCache::throttle('expensive_key', 10, 60, function() {
    return expensiveOperation();
}); // Max 10 regenerations per 60 seconds
SmartCache::rememberWithStampedeProtection()
SmartCache::rememberWithStampedeProtection(string $key, int $ttl, callable $callback, float $beta = 1.0): mixed

Remember with XFetch algorithm for probabilistic early refresh.

$key (string) - Cache key
$ttl (int) - Time to live in seconds
$callback (callable) - Value generator
$beta (float) - Beta factor (higher = earlier refresh)
Returns: mixed - Cached or generated value
Example:
$data = SmartCache::rememberWithStampedeProtection(
    'popular_key', 3600, fn() => expensiveQuery(), 1.0
);
SmartCache::getCircuitBreakerStats()
SmartCache::getCircuitBreakerStats(): array

Get circuit breaker statistics.

Returns: array - Stats (state, failures, successes, last_failure_time)
Example:
$stats = SmartCache::getCircuitBreakerStats();
// Returns: ['state' => 'closed', 'failures' => 0, 'successes' => 5]

🧠 Cost-Aware Caching API

SmartCache::cacheValue()
SmartCache::cacheValue(string $key): ?array

Get value score metadata for a specific cache key.

$key (string) - Cache key to inspect
Returns: ?array - Metadata (cost_ms, access_count, size_bytes, score, last_accessed) or null
Example:
$meta = SmartCache::cacheValue('analytics');
// ['cost_ms' => 800, 'access_count' => 47, 'size_bytes' => 4096, 'score' => 92.4, ...]
SmartCache::getCacheValueReport()
SmartCache::getCacheValueReport(): array

Get a full report of all tracked cache entries sorted by value score (highest first).

Returns: array - List of all tracked keys with their metadata and scores
Example:
$report = SmartCache::getCacheValueReport();
// [
//   ['key' => 'analytics', 'cost_ms' => 800, 'access_count' => 47, 'score' => 92.4],
//   ['key' => 'users',     'cost_ms' => 5,   'access_count' => 120, 'score' => 14.1],
// ]
SmartCache::suggestEvictions()
SmartCache::suggestEvictions(int $count = 10): array

Suggest the lowest-value cache entries for eviction when you need to free space.

$count (int) - Number of eviction candidates to return (default: 10)
Returns: array - List of lowest-score keys with metadata
Example:
$evictable = SmartCache::suggestEvictions(5);
// Returns the 5 lowest-score keys — safest to remove first
foreach ($evictable as $entry) {
    SmartCache::forget($entry['key']);
}
SmartCache::getCostAwareManager()
SmartCache::getCostAwareManager(): ?\SmartCache\Services\CostAwareCacheManager

Get the underlying CostAwareCacheManager instance for advanced usage.

Returns: ?CostAwareCacheManager - Manager instance or null if disabled
Example:
$manager = SmartCache::getCostAwareManager();
if ($manager) {
    echo "Tracking " . $manager->trackedKeyCount() . " keys";
}

🛠️ Cache Management

SmartCache::clear()
SmartCache::clear(): bool

Clear all cache keys managed by SmartCache (tracked keys only).

Returns: bool - True on success
Example:
SmartCache::clear(); // Clear all SmartCache managed keys
SmartCache::flush()
SmartCache::flush(): bool

Flush the entire cache store (all keys, not just SmartCache-managed ones). Equivalent to Laravel's Cache::flush().

Returns: bool - True on success
Example:
SmartCache::flush(); // Flush ALL cache keys (entire store)
SmartCache::getRaw()
SmartCache::getRaw(string $key): mixed

Get the raw (unrestored) value from cache, bypassing optimization strategies. Useful for diagnostics and debugging.

$key (string) - Cache key
Returns: mixed - Raw cached value (may include optimization markers)
Example:
$raw = SmartCache::getRaw('users');
// Returns the raw stored value with compression/chunking markers intact
SmartCache::getManagedKeys()
SmartCache::getManagedKeys(): array

Get all keys currently managed by SmartCache.

Returns: array - List of managed cache keys
Example:
$keys = SmartCache::getManagedKeys();
foreach ($keys as $key) {
    echo "Managed key: {$key}\n";
}

🔧 Helper Functions

smart_cache()
smart_cache(string|array|null $key = null, mixed $value = null, DateTimeInterface|DateInterval|int|null $ttl = null): mixed

Global helper function for SmartCache operations.

$key (string|array|null) - Cache key or key-value array
$value (mixed) - Value to store
$ttl (DateTimeInterface|DateInterval|int|null) - Time to live
Returns: mixed - SmartCache instance or cached value
Examples:
// Get SmartCache instance
$cache = smart_cache();

// Get value
$users = smart_cache('users');

// Set value
smart_cache('users', $users, 3600);

💻 CLI Commands

smart-cache:status
php artisan smart-cache:status [--force]

Display comprehensive information about SmartCache usage, configuration, and performance.

--force (flag) - Include Laravel cache analysis and detailed diagnostics
Examples:
# Basic status overview
php artisan smart-cache:status

# Detailed analysis with recommendations
php artisan smart-cache:status --force
smart-cache:clear
php artisan smart-cache:clear [key] [--force]

Clear SmartCache managed items. Optionally specify a key to clear only that item.

key (optional) - Specific cache key to clear
--force (flag) - Force clear keys even if not managed by SmartCache
Examples:
# Clear all SmartCache managed keys
php artisan smart-cache:clear

# Clear specific key
php artisan smart-cache:clear user_profile_123

# Force clear any cache key
php artisan smart-cache:clear --force
smart-cache:warm
php artisan smart-cache:warm [--keys=]

Pre-populate cache with frequently accessed data using registered warmers.

--keys (optional) - Comma-separated list of specific keys to warm
Examples:
# Warm all registered cache warmers
php artisan smart-cache:warm

# Warm specific keys only
php artisan smart-cache:warm --keys=products,categories
smart-cache:cleanup-chunks
php artisan smart-cache:cleanup-chunks

Clean up orphaned chunks from expired or deleted chunked cache entries.

Examples:
# Run cleanup manually
php artisan smart-cache:cleanup-chunks

# Schedule in Kernel.php
$schedule->command('smart-cache:cleanup-chunks')->daily();
All methods match Laravel's Cache facade API. Optimizations (compression, chunking, invalidation) are applied transparently based on data size and type.

🧪 Testing & Validation

A sample test controller you can drop into your application to validate SmartCache features end-to-end.

Test Controller

The controller below exercises core SmartCache features — basic operations, compression, chunking, SWR patterns, invalidation, and monitoring — and returns structured JSON results.

Controller Implementation


namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use SmartCache\Facades\SmartCache;

class TestSmartCacheDirectlyController extends Controller
{
    public function testSmartCacheFeatures()
    {
        $packageInfo = ['version' => '1.4.2', 'features_tested' => 20];
        $tests = [];

        try {
            // Test 1: Basic Operations
            $tests['basic_operations'] = $this->testBasicOperations();
            
            // Test 2: Compression (2000+ records)
            $tests['compression_test'] = $this->testCompressionFeature();
            
            // Test 3: Chunking (5000+ items)
            $tests['chunking_test'] = $this->testChunkingFeature();
            
            // Test 4: Helper Functions
            $tests['helper_function'] = $this->testHelperFunctions();
            
            // Test 5: SWR Patterns (Laravel 12+)
            if (version_compare(app()->version(), '12.0', '>=')) {
                $tests['swr_patterns'] = $this->testSWRPatterns();
            }
            
            // Test 6: Cache Invalidation & Tags
            $tests['cache_invalidation'] = $this->testCacheInvalidation();
            
            // Test 7: Performance Monitoring
            $tests['performance_monitoring'] = $this->testPerformanceMonitoring();
            
            // Test 8: Advanced Features (remember, locking)
            $tests['advanced_features'] = $this->testAdvancedFeatures();

            return response()->json([
                'message' => 'SmartCache feature tests completed',
                'package_info' => $packageInfo,
                'tests' => $tests,
                'overall_status' => 'success'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'message' => 'SmartCache test failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    private function testBasicOperations()
    {
        $testData = ['data' => 'test_value', 'number' => 123, 'array' => range(1, 10)];

        // Test facade operations
        SmartCache::put('test_facade', $testData, 300);
        $facadeResult = SmartCache::get('test_facade');
        
        // Test helper operations  
        smart_cache(['test_helper' => $testData], 300);
        $helperResult = smart_cache('test_helper');

        return [
            'status' => 'success',
            'facade_results' => [
                'data_integrity' => $testData === $facadeResult,
                'has_key' => SmartCache::has('test_facade')
            ],
            'helper_results' => [
                'data_integrity' => $testData === $helperResult,
                'has_key' => SmartCache::has('test_helper')
            ],
            'both_methods_working' => ($testData === $facadeResult && $testData === $helperResult)
        ];
    }

    // ... Additional test methods for compression, chunking, SWR patterns, etc.
    // See complete implementation in the GitHub Gist
}
📋 Complete Implementation: The full controller code with all test methods, detailed validation logic, and comprehensive error handling is available in the GitHub Gist.

How to Use the Test Controller

1. Installation

Add this controller to your Laravel application:

1 Create the controller:
php artisan make:controller Api/V1/TestSmartCacheDirectlyController
2 Copy the implementation above into your controller
3 Add a route in your routes/api.php:
Route::get('/test-smart-cache', [TestSmartCacheDirectlyController::class, 'testSmartCacheFeatures']);

2. Running the Tests

Access the endpoint to run comprehensive tests:

# Via HTTP request
curl http://your-app.com/api/test-smart-cache

# Or via browser
http://your-app.com/api/test-smart-cache

3. Understanding the Results

The test controller returns a comprehensive JSON response with detailed results:

{
  "message": "SmartCache feature tests completed",
  "package_info": {
    "version": "1.4.2",
    "features_tested": 20
  },
  "tests": {
    "basic_operations": {
      "status": "success",
      "both_methods_working": true,
      "facade_results": { "data_integrity": true, "has_key": true },
      "helper_results": { "data_integrity": true, "has_key": true }
    },
    "compression_test": {
      "status": "success",
      "original_count": 2000,
      "estimated_size_kb": 2207.29,
      "both_methods_successful": true
    },
    "chunking_test": {
      "status": "success", 
      "original_count": 5000,
      "data_matches": true
    },
    "performance_monitoring": {
      "status": "success",
      "monitoring_working": true
    }
    // ... additional test results
  },
  "overall_status": "success"
}
📊 Complete Response: The full JSON response includes detailed metrics for all 20+ features, performance timings, and comprehensive validation results. View the complete response format in the GitHub Gist.

What Each Test Validates

🔧 Basic Operations

Tests put/get/has/forget operations with both facade and helper functions, ensuring data integrity and method compatibility.

📦 Compression Testing

Validates automatic compression with 2000+ records, measuring size reduction and performance impact.

🧩 Chunking Validation

Tests chunking strategy with 5000+ items, verifying data integrity and retrieval performance.

🌊 SWR Patterns

Validates Stale-While-Revalidate patterns, write-through, write-behind, and cache-aside strategies.

🔗 Cache Invalidation

Tests tag-based invalidation, pattern matching, and dependency tracking features.

📊 Performance Monitoring

Validates metrics collection, performance analysis, and automated recommendations.

Tip: Run this controller in staging before deploying to production. It validates data integrity and surfaces any configuration issues early.

Full controller source: GitHub Gist

🔄 Migration Guide

From Laravel Cache

SmartCache implements the same Repository contract as Laravel's Cache facade. Migration requires one import change:

1 Install SmartCache:
composer require iazaran/smart-cache
2 Update your imports:
// Before
use Illuminate\Support\Facades\Cache;

// After
use SmartCache\Facades\SmartCache;
3 Update your code:
// Before
Cache::put('key', $value, 3600);
$value = Cache::get('key');

// SmartCache (works exactly the same, with automatic optimizations)
SmartCache::put('key', $value, 3600);
$value = SmartCache::get('key');
Your existing code works unchanged, with automatic optimizations applied transparently.

Gradual Migration

You can migrate gradually by using both facades:

use Illuminate\Support\Facades\Cache;
use SmartCache\Facades\SmartCache;

// Keep existing code unchanged
Cache::put('old_key', $value, 3600);

// Use SmartCache for optimized caching
SmartCache::put('optimized_key', $value, 3600);
SmartCache::swr('api_data', $callback, 300, 900);

Testing Migration

Test your migration with these commands:

# Test basic functionality
php artisan smart-cache:status

# Test with your application
php artisan tinker
>>> SmartCache::put('test', 'Hello World', 60);
>>> SmartCache::get('test');
=> "Hello World"

Rollback Plan

If you need to rollback, simply change the imports back:

# Change back to Laravel Cache imports in your code
# Then remove SmartCache package
composer remove iazaran/smart-cache
Note: Rolling back will lose SmartCache-specific optimizations, but your data will remain accessible through Laravel's standard cache methods.