PHP Classes

PHP Easy Cache: Cache the contents of remote pages in local files

Recommend this page to a friend!
  Info   Documentation   View files Files   Install with Composer Install with Composer   Download Download   Reputation   Support forum   Blog    
Last Updated Ratings Unique User Downloads Download Rankings
2026-01-03 (-3 hours ago) RSS 2.0 feedNot enough user ratingsTotal: 286 All time: 7,547 This week: 206Up
Version Licenses PHP version Categories
php-easy-cache 1.2.3Freeware, MIT/X C...5.3.0PHP 5, Files and Folders, Cache
Description 

Author

This class can cache the contents of remote pages in local files.

It can retrieve the contents of a remote page with a given URL and store it in a local cache file, so next time the same page is requests it will retrieve from the cache file.

The cache file is stored with a given key name in a configurable cache directory. The cache expiry time is also configurable.

If the contents are in the JSON format, the class will return the decoded JSON value.

The class can also delete a given cached page or flush all expired cache files.

Picture of Hemn Chavroka
  Performance   Level  
Name: Hemn Chavroka <contact>
Classes: 1 package by
Country: Iran Iran
Age: 36
All time rank: 387280 in Iran Iran
Week rank: 195 Up5 in Iran Iran Up

Documentation

PHP EasyCache v3 — PSR‑16 Multi‑Backend Cache with SWR

EasyCache is a pragmatic, batteries‑included cache library that implements the PSR‑16 Simple Cache interface and adds production‑grade features on top:

  • 🚀 Multi‑tier storage: APCu, Redis, File, and PDO (MySQL/PostgreSQL/SQLite)
  • 🔒 Atomic writes and read locks for file storage
  • Full SWR (stale‑while‑revalidate + stale‑if‑error), with non‑blocking per‑key locks
  • 🔧 Pluggable Serializer & Compressor (PHP/JSON + None/Gzip/Zstd)
  • 🔄 Automatic backfill between tiers (e.g., a Redis hit is written back to APCu)
  • 🎯 First‑class Laravel integration via a Service Provider & Facade
  • Comprehensive test coverage with PHPUnit
  • 🛡️ Improved error handling with detailed logging support

> Version: v3.0.1 — Requires PHP 8.1+ and psr/simple-cache:^3.

📖 Documentation in other languages: - فارسی (Persian) - کوردی (Kurdish Sorani)

📦 Installation

composer require iprodev/php-easycache

Optional dependencies

  • `ext-apcu` for the APCu tier
  • `ext-redis` or `predis/predis:^2.0` for the Redis tier
  • `ext-zlib` for Gzip compression
  • `ext-zstd` for Zstd compression

🚀 Quick Start (PSR‑16)

use Iprodev\EasyCache\Cache\MultiTierCache;
use Iprodev\EasyCache\Storage\ApcuStorage;
use Iprodev\EasyCache\Storage\RedisStorage;
use Iprodev\EasyCache\Storage\FileStorage;
use Iprodev\EasyCache\Serialization\NativeSerializer;
use Iprodev\EasyCache\Compression\GzipCompressor;

// Tiers: APCu -> Redis -> File
$apcu  = new ApcuStorage('ec:');

// phpredis (example); predis is also supported
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redisStore = new RedisStorage($redis, 'ec:');

$file  = new FileStorage(__DIR__.'/cache');

$cache = new MultiTierCache(
    [$apcu, $redisStore, $file],
    new NativeSerializer(),
    new GzipCompressor(3),
    defaultTtl: 600
);

// PSR-16 API
$cache->set('user_42', ['id'=>42, 'name'=>'Ava'], 300);
$data = $cache->get('user_42'); // ['id'=>42, 'name'=>'Ava']

🎯 Core Features

1. Multi-Tier Caching

Organize your cache in tiers from fastest to slowest. The library automatically: - Reads from the fastest available tier - Writes to all tiers - Backfills faster tiers when data is found in slower tiers

// Example: Memory -> Redis -> Database
$cache = new MultiTierCache(
    [
        new ApcuStorage('app:'),      // Fast: In-memory
        new RedisStorage($redis),     // Medium: Network cache
        new PdoStorage($pdo, 'cache') // Slow: Database fallback
    ],
    new NativeSerializer(),
    new NullCompressor(),
    3600 // 1 hour default TTL
);

2. Stale-While-Revalidate (SWR)

When data expires but is still inside the SWR window, stale data is served instantly while a refresh happens in the background. This prevents cache stampedes and ensures fast response times.

$result = $cache->getOrSetSWR(
    key: 'posts_homepage',
    producer: function () {
        // Expensive API call or database query
        return fetchPostsFromDatabase();
    },
    ttl: 300,                  // 5 minutes of fresh data
    swrSeconds: 120,           // Serve stale up to 2 minutes after expiry
    staleIfErrorSeconds: 600,  // If refresh fails, serve stale up to 10 minutes
    options: ['mode' => 'defer'] // Defer refresh until after response
);

How it works: 1. If data is fresh, it's returned immediately 2. If data is expired but within SWR window: - Stale data is returned instantly - Background refresh is triggered (non-blocking) 3. If refresh fails, stale data continues to be served (within staleIfError window)

3. Pluggable Serialization

Choose the serializer that fits your needs:

// PHP Native Serializer (supports objects)
use Iprodev\EasyCache\Serialization\NativeSerializer;
$cache = new MultiTierCache([$storage], new NativeSerializer());

// JSON Serializer (portable, faster for simple data)
use Iprodev\EasyCache\Serialization\JsonSerializer;
$cache = new MultiTierCache([$storage], new JsonSerializer());

4. Pluggable Compression

Save memory and disk space:

// No compression
use Iprodev\EasyCache\Compression\NullCompressor;
$cache = new MultiTierCache([$storage], $serializer, new NullCompressor());

// Gzip compression (balanced)
use Iprodev\EasyCache\Compression\GzipCompressor;
$cache = new MultiTierCache([$storage], $serializer, new GzipCompressor(5));

// Zstd compression (fastest)
use Iprodev\EasyCache\Compression\ZstdCompressor;
$cache = new MultiTierCache([$storage], $serializer, new ZstdCompressor(3));

💾 Storage Backends

APCu Storage

Fast in-memory cache, perfect as the first tier.

use Iprodev\EasyCache\Storage\ApcuStorage;

$storage = new ApcuStorage(
    prefix: 'myapp:' // Namespace your keys
);

Features: - Lightning-fast memory access - Shared between PHP-FPM workers - Automatic expiration - Safe clear() that only deletes prefixed keys

Redis Storage

Network-based cache with persistence options.

use Iprodev\EasyCache\Storage\RedisStorage;

// Using phpredis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$storage = new RedisStorage($redis, 'myapp:');

// Using predis
$redis = new Predis\Client('tcp://127.0.0.1:6379');
$storage = new RedisStorage($redis, 'myapp:');

Features: - Works with phpredis or predis - TTL support with SETEX - Safe clear() with prefix scanning - Automatic expiration

File Storage

Reliable disk-based cache with sharding.

use Iprodev\EasyCache\Storage\FileStorage;

$storage = new FileStorage(
    path: '/var/cache/myapp',  // Cache directory
    ext: '.cache',              // File extension
    shards: 2                   // Directory sharding level (0-3)
);

Features: - Atomic writes (temp file + rename) - Read locks with flock() - Directory sharding for performance - Configurable file extension

Directory Sharding Example:

With shards=2, key "user_123" (hash: a1b2c3d4):
/var/cache/myapp/a1/b2/a1b2c3d4.cache

PDO Storage

SQL database cache for shared environments.

use Iprodev\EasyCache\Storage\PdoStorage;

$pdo = new PDO('mysql:host=localhost;dbname=cache', 'user', 'pass');
$storage = new PdoStorage($pdo, 'easycache');

// Create table (run once during setup)
$storage->ensureTable();

Supported databases: - SQLite: sqlite:/path/to/cache.db - MySQL: mysql:host=localhost;dbname=cache - PostgreSQL: pgsql:host=localhost;dbname=cache

Features: - TTL support with expiration check - Prune expired items with prune() - UPSERT support (INSERT ... ON CONFLICT) - Indexed queries for performance

🎨 Complete Examples

Example 1: Simple File Cache

use Iprodev\EasyCache\Cache\MultiTierCache;
use Iprodev\EasyCache\Storage\FileStorage;
use Iprodev\EasyCache\Serialization\NativeSerializer;
use Iprodev\EasyCache\Compression\NullCompressor;

$storage = new FileStorage(__DIR__ . '/cache');
$cache = new MultiTierCache([$storage], new NativeSerializer(), new NullCompressor());

// Set with 1 hour TTL
$cache->set('user_profile', [
    'id' => 123,
    'name' => 'John Doe',
    'email' => '[email protected]'
], 3600);

// Get
$profile = $cache->get('user_profile');

// Check existence
if ($cache->has('user_profile')) {
    echo "Profile is cached!";
}

// Delete
$cache->delete('user_profile');

Example 2: Multi-Tier with Backfill

// Setup: APCu (fast) -> Redis (medium) -> File (slow)
$apcu = new ApcuStorage('app:');
$redis = new RedisStorage($redisClient, 'app:');
$file = new FileStorage('/var/cache/app');

$cache = new MultiTierCache([$apcu, $redis, $file]);

// First request: Cache miss, data fetched and stored in all tiers
$data = $cache->get('expensive_data');

// APCu crashes and restarts...

// Next request: Data found in Redis, automatically backfilled to APCu
$data = $cache->get('expensive_data'); // Fast!

Example 3: SWR for API Responses

use Psr\Log\LoggerInterface;

$cache = new MultiTierCache(
    [$apcu, $redis],
    new NativeSerializer(),
    new GzipCompressor(5),
    600, // 10 min default TTL
    $logger // Optional PSR-3 logger
);

$posts = $cache->getOrSetSWR(
    key: 'api_posts_latest',
    producer: function() use ($apiClient) {
        // This is expensive
        return $apiClient->fetchPosts();
    },
    ttl: 300,          // Fresh for 5 minutes
    swrSeconds: 60,    // Serve stale for 1 minute while refreshing
    staleIfErrorSeconds: 300, // Serve stale for 5 minutes if API fails
    options: ['mode' => 'defer'] // Refresh after response sent
);

Example 4: Batch Operations

// Set multiple
$cache->setMultiple([
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3',
], 3600);

// Get multiple with default
$results = $cache->getMultiple(['key1', 'key2', 'missing'], 'default');
// ['key1' => 'value1', 'key2' => 'value2', 'missing' => 'default']

// Delete multiple
$cache->deleteMultiple(['key1', 'key2']);

Example 5: DateInterval TTL

// Cache for 2 hours
$cache->set('key', 'value', new DateInterval('PT2H'));

// Cache for 1 day
$cache->set('key', 'value', new DateInterval('P1D'));

// Cache for 30 days
$cache->set('key', 'value', new DateInterval('P30D'));

Example 6: Custom Logger Integration

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('cache');
$logger->pushHandler(new StreamHandler('/var/log/cache.log', Logger::WARNING));

$cache = new MultiTierCache(
    [$storage],
    new NativeSerializer(),
    new NullCompressor(),
    3600,
    $logger // Will log warnings and errors
);

Example 7: Scheduled Cleanup

// Run this in a cron job or scheduled task
$pruned = $cache->prune();
echo "Pruned {$pruned} expired items";

// For PDO storage, this removes expired rows
// For File/APCu/Redis, expiration is automatic

🎭 Laravel Integration

Setup

  1. Install the package:
    composer require iprodev/php-easycache
    
  2. Publish configuration:
    php artisan vendor:publish --tag=easycache-config
    
  3. Configure in config/easycache.php:
    return [
    'drivers' => ['apcu', 'redis', 'file'],
    'default_ttl' => 600,
    
    'serializer' => [
        'driver' => 'php', // php|json
    ],
    
    'compressor' => [
        'driver' => 'gzip', // none|gzip|zstd
        'level' => 5,
    ],
    
    'redis' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'port' => env('REDIS_PORT', 6379),
        'password' => env('REDIS_PASSWORD', null),
        'database' => env('REDIS_CACHE_DB', 1),
    ],
    ];
    

Using the Facade

use EasyCache;

// Simple operations
EasyCache::set('user_settings', $settings, 3600);
$settings = EasyCache::get('user_settings');

// SWR pattern
$data = EasyCache::getOrSetSWR(
    'dashboard_stats',
    fn() => $this->computeStats(),
    300,  // Fresh for 5 min
    60,   // SWR for 1 min
    300   // Stale-if-error for 5 min
);

// Batch operations
EasyCache::setMultiple([
    'key1' => 'value1',
    'key2' => 'value2',
]);

Artisan Commands

The package includes a prune command:

# Prune expired cache items
php artisan easycache:prune

# Add to your scheduler (app/Console/Kernel.php)
$schedule->command('easycache:prune')->daily();

🔑 Key Rules (PSR‑16)

  • Allowed characters: `[A-Za-z0-9_.]`
  • Max length: 64 characters
  • Reserved characters (not allowed): `{ } ( ) / \ @ :`
// Valid keys
$cache->set('user_123', $data);
$cache->set('posts.latest', $data);
$cache->set('CamelCase', $data);

// Invalid keys (will throw InvalidArgument exception)
$cache->set('user:123', $data);    // Contains :
$cache->set('user/123', $data);    // Contains /
$cache->set('user@123', $data);    // Contains @
$cache->set(str_repeat('x', 65), $data); // Too long

🧪 Testing & Quality Assurance

Running Tests

# Run all tests
composer test

# Run with coverage
composer test -- --coverage-html coverage

# Run specific test suite
./vendor/bin/phpunit --testsuite "Storage Tests"

Static Analysis

# Run PHPStan
composer stan

# Check coding standards
composer cs

# Fix coding standards automatically
composer cs:fix

Test Coverage

The library includes comprehensive tests for: - ✅ All storage backends (File, APCu, Redis, PDO) - ✅ Multi-tier caching with backfill - ✅ SWR functionality - ✅ Serializers (Native, JSON) - ✅ Compressors (Null, Gzip, Zstd) - ✅ Key validation - ✅ Lock mechanism - ✅ Edge cases and error handling

🔧 Advanced Configuration

Custom Lock Path

$cache = new MultiTierCache(
    [$storage],
    $serializer,
    $compressor,
    3600,
    $logger,
    '/custom/lock/path' // Custom lock directory
);

File Storage Sharding Levels

// No sharding: /cache/md5hash.cache
$storage = new FileStorage('/cache', '.cache', 0);

// 1 level: /cache/a1/md5hash.cache
$storage = new FileStorage('/cache', '.cache', 1);

// 2 levels: /cache/a1/b2/md5hash.cache (recommended)
$storage = new FileStorage('/cache', '.cache', 2);

// 3 levels: /cache/a1/b2/c3/md5hash.cache
$storage = new FileStorage('/cache', '.cache', 3);

Environment Variables (Laravel)

# .env file
EASYCACHE_DRIVER=redis
EASYCACHE_REDIS_HOST=127.0.0.1
EASYCACHE_REDIS_PORT=6379
EASYCACHE_REDIS_PASSWORD=secret
EASYCACHE_REDIS_DB=1
EASYCACHE_DEFAULT_TTL=600

🚨 Error Handling

All storage operations are wrapped with proper error handling. Failures are logged (if logger is provided) and don't crash your application:

use Monolog\Logger;

$logger = new Logger('cache');
$cache = new MultiTierCache([$storage], $serializer, $compressor, 3600, $logger);

// If storage fails, operation returns false but doesn't throw
$result = $cache->set('key', 'value');
if (!$result) {
    // Check logs for details
    echo "Cache set failed, check logs";
}

Logged Events: - Storage read/write failures - Compression/decompression errors - Lock acquisition failures - SWR refresh errors - Serialization errors

🔄 Backwards Compatibility

For projects upgrading from v2, use the BC wrapper:

use Iprodev\EasyCache\EasyCache;

$cache = new EasyCache([
    'cache_path' => __DIR__ . '/cache',
    'cache_extension' => '.cache',
    'cache_time' => 3600,
    'directory_shards' => 2,
]);

// Works like v2
$cache->set('key', 'value');
$value = $cache->get('key');

📝 Best Practices

  1. Use multi-tier wisely: APCu → Redis → File/PDO
  2. Set appropriate TTLs: Balance freshness vs. performance
  3. Use SWR for expensive operations: Prevent cache stampedes
  4. Monitor cache hit rates: Use logging to track performance
  5. Schedule pruning: For PDO storage, prune regularly
  6. Use compression for large data: GzipCompressor or ZstdCompressor
  7. Namespace your keys: Use prefixes to avoid collisions
  8. Test error scenarios: Ensure your app handles cache failures gracefully

🤝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

Development Setup

git clone https://github.com/iprodev/php-easycache.git
cd php-easycache
composer install
composer test

📄 License

MIT © iprodev

🔗 Links

💬 Support


  Files folder image Files (55)  
File Role Description
Files folder image.github (3 files, 2 directories)
Files folder imagebin (1 file)
Files folder imageconfig (1 file)
Files folder imageexamples (1 file)
Files folder imagesrc (1 file, 7 directories)
Files folder imagetests (5 directories)
Accessible without login Plain text file API.md Data Auxiliary data
Accessible without login Plain text file API_FA.md Data Auxiliary data
Accessible without login Plain text file API_KU.md Data Auxiliary data
Accessible without login Plain text file CHANGELOG.md Data Auxiliary data
Accessible without login Plain text file CODE_OF_CONDUCT.md Data Auxiliary data
Accessible without login Plain text file composer.json Data Auxiliary data
Plain text file CONTRIBUTING.md Class Class source
Plain text file EXAMPLES.md Class Class source
Plain text file EXAMPLES_FA.md Class Class source
Plain text file EXAMPLES_KU.md Class Class source
Accessible without login Plain text file LICENSE.md Lic. License text
Accessible without login Plain text file MIGRATION.md Data Auxiliary data
Accessible without login Plain text file PERFORMANCE.md Data Auxiliary data
Accessible without login Plain text file phpstan.neon Data Auxiliary data
Accessible without login Plain text file phpunit.xml Data Auxiliary data
Accessible without login Plain text file README.md Doc. Documentation
Accessible without login Plain text file README_FA.md Doc. Documentation
Plain text file README_KU.md Class Class source
Accessible without login Plain text file RELEASING.md Data Auxiliary data
Accessible without login Plain text file SECURITY.md Data Auxiliary data
Plain text file TROUBLESHOOTING.md Class Class source

  Files folder image Files (55)  /  .github  
File Role Description
Files folder imageISSUE_TEMPLATE (2 files)
Files folder imageworkflows (1 file)
  Accessible without login Plain text file dependabot.yml Data Auxiliary data
  Accessible without login Plain text file FUNDING.yml Data Auxiliary data
  Accessible without login Plain text file PULL_REQUEST_TEMPLATE.md Data Auxiliary data

  Files folder image Files (55)  /  .github  /  ISSUE_TEMPLATE  
File Role Description
  Accessible without login Plain text file bug_report.md Data Auxiliary data
  Accessible without login Plain text file feature_request.md Data Auxiliary data

  Files folder image Files (55)  /  .github  /  workflows  
File Role Description
  Accessible without login Plain text file ci.yml Data Auxiliary data

  Files folder image Files (55)  /  bin  
File Role Description
  Accessible without login Plain text file easycache-prune Example Example script

  Files folder image Files (55)  /  config  
File Role Description
  Accessible without login Plain text file easycache.php Aux. Configuration script

  Files folder image Files (55)  /  examples  
File Role Description
  Accessible without login Plain text file swr.php Example Example script

  Files folder image Files (55)  /  src  
File Role Description
Files folder imageCache (1 file)
Files folder imageCompression (4 files)
Files folder imageExceptions (1 file)
Files folder imageLaravel (1 file, 1 directory)
Files folder imageSerialization (3 files)
Files folder imageStorage (5 files)
Files folder imageUtil (2 files)
  Plain text file EasyCache.php Class Class source

  Files folder image Files (55)  /  src  /  Cache  
File Role Description
  Plain text file MultiTierCache.php Class Class source

  Files folder image Files (55)  /  src  /  Compression  
File Role Description
  Plain text file CompressorInterface.php Class Class source
  Plain text file GzipCompressor.php Class Class source
  Plain text file NullCompressor.php Class Class source
  Plain text file ZstdCompressor.php Class Class source

  Files folder image Files (55)  /  src  /  Exceptions  
File Role Description
  Plain text file InvalidArgument.php Class Class source

  Files folder image Files (55)  /  src  /  Laravel  
File Role Description
Files folder imageFacades (1 file)
  Plain text file EasyCacheServiceProvider.php Class Class source

  Files folder image Files (55)  /  src  /  Laravel  /  Facades  
File Role Description
  Plain text file EasyCache.php Class Class source

  Files folder image Files (55)  /  src  /  Serialization  
File Role Description
  Plain text file JsonSerializer.php Class Class source
  Plain text file NativeSerializer.php Class Class source
  Plain text file SerializerInterface.php Class Class source

  Files folder image Files (55)  /  src  /  Storage  
File Role Description
  Plain text file ApcuStorage.php Class Class source
  Plain text file FileStorage.php Class Class source
  Plain text file PdoStorage.php Class Class source
  Plain text file RedisStorage.php Class Class source
  Plain text file StorageInterface.php Class Class source

  Files folder image Files (55)  /  src  /  Util  
File Role Description
  Plain text file KeyValidator.php Class Class source
  Plain text file Lock.php Class Class source

  Files folder image Files (55)  /  tests  
File Role Description
Files folder imageCache (1 file)
Files folder imageCompression (1 file)
Files folder imageSerialization (1 file)
Files folder imageStorage (1 file)
Files folder imageUtil (2 files)

  Files folder image Files (55)  /  tests  /  Cache  
File Role Description
  Plain text file MultiTierCacheTest.php Class Class source

  Files folder image Files (55)  /  tests  /  Compression  
File Role Description
  Plain text file CompressorTest.php Class Class source

  Files folder image Files (55)  /  tests  /  Serialization  
File Role Description
  Plain text file SerializerTest.php Class Class source

  Files folder image Files (55)  /  tests  /  Storage  
File Role Description
  Plain text file FileStorageTest.php Class Class source

  Files folder image Files (55)  /  tests  /  Util  
File Role Description
  Plain text file KeyValidatorTest.php Class Class source
  Plain text file LockTest.php Class Class source

The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page.
Install with Composer Install with Composer
 Version Control Unique User Downloads Download Rankings  
 100%
Total:286
This week:0
All time:7,547
This week:206Up