league/flysystem-cached-adapter
Caching adapter for Flysystem that speeds up filesystem operations by storing metadata (like directory listings and file info) in a cache backend. Reduces repeated calls to slower storage (S3/FTP) and improves performance in read-heavy scenarios.
Installation
composer require league/flysystem-cached-adapter
Ensure you have a base FlySystem adapter (e.g., league/flysystem-aws-s3-v3, league/flysystem-local) already configured.
Basic Setup
use League\Flysystem\Cached\CachedAdapter;
use League\Flysystem\Filesystem;
use League\Flysystem\Adapter\LocalAdapter;
$adapter = new LocalAdapter('/path/to/storage');
$cache = new CachedAdapter($adapter, [
'cache' => new \League\Flysystem\Cached\Storage\Psr6CacheStorage(
new \Symfony\Component\Cache\Adapter\FilesystemAdapter()
)
]);
$filesystem = new Filesystem($cache);
First Use Case
Benchmark file operations (e.g., listContents(), fileExists()) before/after caching to observe performance gains. Example:
$files = $filesystem->listContents('/');
// Subsequent calls to `listContents()` will use cached metadata.
Decorating Existing Adapters
Wrap any FlySystem adapter (S3, FTP, Rackspace, etc.) with CachedAdapter to cache metadata (e.g., file sizes, timestamps, checksums).
$s3Adapter = new AwsS3Adapter(...);
$cachedS3 = new CachedAdapter($s3Adapter, ['cache' => $cache]);
Cache Storage Backends
symfony/cache, stash, predis).
$cache = new Psr6CacheStorage(new PredisCache());
cache/ directory).
$cache = new FilesystemCacheStorage('/path/to/cache');
Cache Invalidation Manually clear cache for specific files/directories:
$cache->invalidateMetadata('path/to/file.txt');
$cache->invalidateMetadata('path/to/directory/');
Or clear all cache:
$cache->clearCache();
Conditional Caching Disable caching for specific operations via config:
$adapter = new CachedAdapter($baseAdapter, [
'cache' => $cache,
'skipCache' => ['delete', 'write*'] // Skip caching for delete/write operations
]);
Integration with Laravel
public function register()
{
$this->app->singleton('filesystem.cached', function ($app) {
$adapter = $app['filesystem']->adapter();
return new CachedAdapter($adapter, [
'cache' => new Psr6CacheStorage($app['cache.store'])
]);
});
}
'disks' => [
'cached-s3' => [
'driver' => 'cached',
'adapter' => 's3',
'cache' => 'array', // or 'redis', 'file', etc.
],
],
Custom Cache Keys Override cache key generation for complex paths:
$adapter = new CachedAdapter($baseAdapter, [
'cache' => $cache,
'cacheKeyGenerator' => function ($path) {
return 'custom_prefix_' . md5($path);
}
]);
Cache Staleness
invalidateMetadata() after external writes.
$cache->setCacheTTL(3600); // 1-hour cache expiry
Write Operation Overhead
write, delete, and rename operations because metadata must be updated.skipCache config).Memory Usage
symfony/cache-filesystem) for high-volume systems.Concurrent Writes
symfony/lock) for critical sections.Cache Key Collisions
cacheKeyGenerator functions must avoid collisions (e.g., /path vs /path/).rtrim($path, '/')) in the generator.Laravel Caching Quirks
array driver for production).file, redis, or database drivers for production.Verify Cache Hits/Misses Enable debug logging for the cache storage:
$cache = new Psr6CacheStorage($psr6Cache, [
'debug' => true
]);
Check logs for CACHE_HIT/CACHE_MISS entries.
Inspect Cache Contents Dump the cache storage to verify metadata:
$cache->getCache()->getItem('path/to/file.txt')->get();
Test Cache Invalidation
Write a test to ensure invalidateMetadata() works:
$filesystem->write('test.txt', 'content');
$filesystem->invalidateMetadata('test.txt');
$this->assertFalse($filesystem->has('test.txt')); // May not work; test metadata specifically.
Custom Cache Storage
Implement League\Flysystem\Cached\Storage\CacheStorageInterface for custom backends (e.g., database, custom Redis hashes).
Event Listeners Hook into FlySystem events to invalidate cache dynamically:
$filesystem->addListener('after.*', function ($event) {
if ($event->getOperation() === 'write') {
$this->cachedAdapter->invalidateMetadata($event->getPath());
}
});
Cache Warmers Pre-load cache for frequently accessed files/directories during low-traffic periods:
$filesystem->listContents('/');
$filesystem->listContents('/assets/');
Hybrid Caching
Combine with league/flysystem-cache for file content caching:
$adapter = new CachedAdapter(
new CacheAdapter($baseAdapter, $cache),
['cache' => $metadataCache]
);
How can I help you explore Laravel packages today?