jarir-ahmed/cache
最新稳定版本:v1.1.0
Composer 安装命令:
composer require jarir-ahmed/cache
包简介
Framework-agnostic caching toolkit for PHP: PSR-16 + PSR-6, Redis/Memcached/APCu/File/PDO/tiered stores, tags, atomic locks, stampede protection, and HTTP caching (ETag/304, full-page).
README 文档
README
A framework-agnostic caching toolkit for PHP — every common cache type behind one clean API: in-memory, file, APCu, Redis, Memcached, PDO (database), and tiered (multi-layer). Plus PSR-16 + PSR-6 for drop-in use in any framework, tags, atomic locks, stampede protection, and HTTP caching (ETag/304, full-page, PSR-15 middleware).
Zero required dependencies beyond the PSR cache interfaces. Redis and Memcached work with no PHP extension (built-in raw-socket clients) and automatically use ext-redis / ext-memcached when present.
Install
composer require jarir-ahmed/cache
Why
"Framework-level caching for any framework" = implement the standards. This package is a PSR-16 and PSR-6 implementation, so it drops straight into Laravel, Symfony, Slim, Mezzio, Doctrine, or raw PHP — while also giving you a richer native API and an HTTP caching layer most libraries skip.
Quick start
use JarirAhmed\Cache\Cache; use JarirAhmed\Cache\Store\ArrayStore; $cache = Cache::repository(new ArrayStore); $cache->set('key', 'value', 60); // ttl seconds (null = forever) $cache->get('key', 'default'); $cache->remember('user:1', 300, fn () => loadUser(1)); // compute once, then cache $cache->increment('hits'); $cache->tags(['users'])->flush();
Config-driven, named stores
$cache = Cache::create([ 'default' => 'redis', 'prefix' => 'app:', 'serializer' => 'php', // php | json | igbinary 'stores' => [ 'redis' => ['driver' => 'redis', 'host' => '127.0.0.1', 'port' => 6379], 'memcached' => ['driver' => 'memcached', 'host' => '127.0.0.1', 'port' => 11211], 'files' => ['driver' => 'file', 'path' => '/var/cache/app'], 'db' => ['driver' => 'pdo', 'pdo' => $pdo, 'table' => 'cache'], 'fast' => ['driver' => 'tiered', 'layers' => ['array', 'redis']], ], ]); $cache->store('redis')->set('k', $value, 3600); $cache->store('fast')->remember('hot', 60, fn () => compute());
Stores
| Driver | Class | Notes |
|---|---|---|
array |
ArrayStore |
per-request memory |
file |
FileStore |
sharded dirs, atomic writes |
apcu |
ApcuStore |
shared memory (ext-apcu) |
redis |
RedisStore |
raw-socket RESP or ext-redis |
memcached |
MemcachedStore |
raw-socket text proto or ext-memcached |
pdo |
PdoStore |
sqlite/mysql/pgsql, self-creating table |
null |
NullStore |
disables caching |
tiered |
TieredStore |
L1+L2, read-through back-fill |
Redis without any extension:
use JarirAhmed\Cache\Store\RedisStore; $redis = Cache::repository(RedisStore::connect('127.0.0.1', 6379)); // uses ext-redis if loaded, else raw socket
PSR-16 and PSR-6 (use it in any framework)
$psr16 = Cache::psr16(new RedisStore(...)); // Psr\SimpleCache\CacheInterface $psr16->set('k', 'v', 3600); $pool = Cache::psr6(new FileStore('/tmp')); // Psr\Cache\CacheItemPoolInterface $item = $pool->getItem('k'); if (! $item->isHit()) { $item->set(compute())->expiresAfter(600); $pool->save($item); }
- Symfony: pass the PSR-6 pool anywhere a
CacheItemPoolInterfaceis expected. - Doctrine: same — it consumes PSR-6.
- Laravel: use
Bridge\LaravelStoreto register a custom driver (Cache::extend(...)).
Tags
$cache->tags(['users', 'profiles'])->put('u:1', $data, 3600); $cache->tags(['users'])->flush(); // invalidate every 'users' entry at once
Atomic locks & stampede protection
// distributed lock $cache->lock('import', 30)->get(function () { runImportOnce(); // only one process at a time }); // single-flight: under load, ONE caller computes, the rest wait for the result $report = $cache->rememberLocked('daily-report', 600, fn () => buildExpensiveReport());
HTTP caching
use JarirAhmed\Cache\Http\HttpCache; use JarirAhmed\Cache\Http\CacheControl; echo HttpCache::serve($body, [ 'etag' => true, 'cache_control' => CacheControl::make()->public()->maxAge(300)->staleWhileRevalidate(60), ]); // emits ETag + Cache-Control, replies 304 automatically on If-None-Match
Full-page cache:
use JarirAhmed\Cache\Http\PageCache; $page = new PageCache($cache->store(), ttl: 120); if (($html = $page->start('home')) !== null) { echo $html; return; } // cache hit // ... render your page ... echo $page->end('home'); // capture + store
PSR-15 middleware (Slim/Mezzio/Laminas):
use JarirAhmed\Cache\Http\CacheMiddleware; $app->add(new CacheMiddleware($cache->store(), $psr17ResponseFactory, ttl: 60));
Serializers
php (default, any value), json (portable, scalars/arrays), igbinary (compact binary, needs ext-igbinary). Set per store via the serializer config key or pass a Serializer instance.
Architecture
Store (contract) ─ Array | File | Apcu | Redis | Memcached | Pdo | Null | Tiered
Repository ─ rich API (remember/add/pull/increment/tags/lock/rememberLocked) over a Store
Psr16Cache / Psr6Pool ─ standards adapters
Lock + StoreLock ─ atomic mutex (single-flight)
Tags: TagSet + TaggedCache ─ group invalidation
Http: CacheControl, HttpCache (ETag/304), PageCache, CacheMiddleware (PSR-15)
Cache / CacheManager ─ factory + named stores
Testing
composer test
The suite runs one shared contract against every store. Redis/Memcached tests run when those servers are reachable and skip otherwise; raw-socket and extension paths are both covered.
License
MIT.
统计信息
- 总下载量: 1
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-10