beste/in-memory-cache
PSR-6 in-memory cache for PHP, ideal as a default cache or for tests. Lightweight CacheItemPool implementation with support for expiration and optional PSR-20 clock injection (e.g., frozen clocks) to control time in tests.
Installation:
composer require beste/in-memory-cache
Basic Usage:
use Beste\Cache\InMemoryCache;
$cache = new InMemoryCache();
$item = $cache->getItem('test_key');
$item->set('test_value')->expiresAfter(60); // 60 seconds TTL
$cache->save($item);
// Retrieve later
$hitItem = $cache->getItem('test_key');
if ($hitItem->isHit()) {
echo $hitItem->get(); // 'test_value'
}
Laravel Integration:
Add to config/cache.php under stores:
'in_memory' => [
'driver' => 'cache',
'store' => Beste\Cache\InMemoryCache::class,
],
Then use in .env for testing:
CACHE_DRIVER=in_memory
Testing Cache-Dependent Logic: Replace Redis/Memcached in unit tests with deterministic in-memory cache:
public function testCacheBehavior()
{
$cache = new InMemoryCache();
$cache->save($cache->getItem('user:1')->set(['name' => 'John']));
$this->assertEquals(['name' => 'John'], $cache->getItem('user:1')->get());
}
Testing Workflow:
InMemoryCache directly for isolated cache assertions.Cache facade to use in_memory driver via .env:
CACHE_DRIVER=in-memory
beste/clock for TTL validation:
use Beste\Clock\FrozenClock;
$clock = FrozenClock::fromUTC();
$cache = new InMemoryCache($clock);
$item = $cache->getItem('time_test');
$item->set('value')->expiresAfter(new DateInterval('PT1H'));
$cache->save($item);
$clock->setTo($clock->now()->add(new DateInterval('PT2H')));
$this->assertFalse($cache->getItem('time_test')->isHit());
Production Fallback:
config/cache.php:
'stores' => [
'in_memory' => [
'driver' => 'cache',
'store' => Beste\Cache\InMemoryCache::class,
'as' => 'fallback', // Custom alias
],
],
try {
return Cache::get('key');
} catch (CacheException $e) {
return Cache::store('fallback')->get('key');
}
Local Development:
CACHE_DRIVER in .env:
CACHE_DRIVER=in-memory
Laravel Cache Facade:
Use Cache::store('in_memory') for explicit driver selection:
Cache::store('in_memory')->put('temp_key', 'temp_value', now()->addMinutes(5));
Tagging Support: Extend the cache to support Laravel’s tagging system by wrapping the store:
use Illuminate\Cache\TaggingStore;
$cache = new TaggingStore(new InMemoryCache());
$cache->tags(['users'])->put('user:1', ['name' => 'John']);
Event Listeners:
Leverage PSR-6’s save()/delete() events for custom logic:
$cache->save($item); // Triggers cache events
Dependency Injection: Bind the cache in Laravel’s service container:
$app->bind(Beste\Cache\InMemoryCache::class, function () {
return new InMemoryCache();
});
Memory Leaks:
expiresAfter()) or manually clear the cache:
$cache->clear(); // Clears all items
Thread/Process Safety:
Serialization Limits:
serialize() helper or implement __serialize()/__unserialize():
$item->set(serialize($complexObject));
$data = $item->get();
$object = unserialize($data);
Key Validation:
+) may fail silently.Str::slug():
$key = Str::slug('user profile');
TTL Precision:
Beste\Clock\FrozenClock for deterministic TTL testing.$items = [];
foreach ($cache->getMetadata('*') as $key => $metadata) {
$items[$key] = $cache->getItem($key)->get();
}
$item = $cache->getItem('key');
$expiry = $item->getExpiration();
Clock Dependency:
PSR-20 clock. Omit it for default system time:
$cache = new InMemoryCache(); // Uses system clock
$cache = new InMemoryCache(new FrozenClock());
Laravel Cache Driver:
config/cache.php:
'stores' => [
'in_memory' => [
'driver' => 'cache',
'store' => Beste\Cache\InMemoryCache::class,
],
],
Custom Metadata: Extend the cache to store additional metadata:
$item->setMetadata(['source' => 'api']);
$metadata = $item->getMetadata();
Event Dispatching:
Wrap the cache to dispatch events (e.g., CacheStored, CacheMissed):
$cache = new EventDispatchingCache(new InMemoryCache());
Hybrid Cache: Combine with other stores (e.g., fallback to Redis):
$cache = new HybridCache(new InMemoryCache(), new RedisCache());
Size Limits:
Implement a custom eviction policy (e.g., LRU) by extending InMemoryCache:
class LimitedInMemoryCache extends InMemoryCache {
public function __construct(int $maxItems = 1000) {
parent::__construct();
$this->maxItems = $maxItems;
}
public function save(ItemInterface $item): bool {
if ($this->count() >= $this->maxItems) {
$this->clear(); // Or implement LRU
}
return parent::save($item);
}
}
if ($cache->count() > 1000) {
$cache->clear();
}
How can I help you explore Laravel packages today?