beste/in-memory-cache
Lightweight PSR-6 in-memory cache for PHP. Ideal as a default cache implementation and for fast, dependency-free tests. Supports expirations and can use a PSR-20 clock (e.g. frozen clock) for deterministic time-based behavior.
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');
$cache->save($item);
// Retrieve later
$retrievedItem = $cache->getItem('test_key');
$value = $retrievedItem->get(); // 'test_value'
Laravel Integration:
Register the cache driver in config/cache.php:
'drivers' => [
'in_memory' => [
'driver' => 'cache',
'store' => Beste\Cache\InMemoryCache::class,
],
],
Then set the driver in .env:
CACHE_DRIVER=in_memory
First Use Case: Replace Redis/Memcached in local development or tests to avoid external dependencies:
// In a test file
public function test_cache_functionality()
{
$cache = new Beste\Cache\InMemoryCache();
$cache->set('test', 'value', now()->addMinutes(10));
$this->assertEquals('value', $cache->get('test'));
}
Testing Workflows:
$cache = new Beste\Cache\InMemoryCache();
$cache->set('user_data', $user, 300); // 5 minutes TTL
$this->assertEquals($user, $cache->get('user_data'));
beste/clock for deterministic expiry tests:
use Beste\Clock\FrozenClock;
$clock = FrozenClock::fromUTC();
$cache = new Beste\Cache\InMemoryCache($clock);
$cache->set('time_test', 'value', now()->addMinutes(5));
$clock->setTo($clock->now()->addMinutes(6));
$this->assertNull($cache->get('time_test')); // Expired
Laravel-Specific Patterns:
Cache::tags() with in-memory cache (though tags are not natively supported by PSR-6, you can implement a wrapper):
class TaggedInMemoryCache extends Beste\Cache\InMemoryCache
{
public function tags(array $tags): void
{
// Custom logic to handle tags
}
}
Cache::store() events (e.g., Cache::store('in_memory')->flush()) to clear the cache programmatically.Fallback Strategy:
Cache facade:
Cache::store('in_memory')->remember('fallback_key', 60, function () {
return App::make('expensive_service')->fetchData();
});
Memory Management:
$cache->clear(); // PSR-6 method
expiresAfter() or expiresAt() to auto-cleanup:
$item = $cache->getItem('temp_data');
$item->set('data')->expiresAfter(new DateInterval('PT1H'));
$cache->save($item);
PSR-6 Adapter:
Cache facade using a PSR-6 adapter (e.g., spatie/laravel-cache):
Cache::extend('in_memory', function ($app) {
return new CacheManager([
'store' => Beste\Cache\InMemoryCache::class,
]);
});
Clock Integration:
Beste\Clock\FrozenClock to control expiry:
$clock = FrozenClock::fromUTC();
$cache = new Beste\Cache\InMemoryCache($clock);
Hybrid Caching:
// config/cache.php
'default' => env('CACHE_DRIVER', 'redis'),
'stores' => [
'in_memory' => [
'driver' => 'cache',
'store' => Beste\Cache\InMemoryCache::class,
],
'redis' => [
'driver' => 'redis',
// Redis config...
],
],
Serialization Handling:
serialize() helper:
$data = ['user' => User::find(1)];
$cache->set('complex_data', serialize($data), 300);
$cachedData = unserialize($cache->get('complex_data'));
No Persistence:
Cache::clear() in long-running processes.Thread Safety:
Swoole\Atomic).Memory Bloat:
$cache->clear(); // After tests or batch operations
Key Validation:
$key = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', $rawKey);
Serialization Limits:
serialize() for custom objects or avoid caching them.Laravel Cache Facade Quirks:
Cache::tags()) are not PSR-6-compliant.$cache->getItem('key')->set('value')->expiresAfter(60);
$cache->save($cache->getItem('key'));
Inspect Cache Contents:
class DebugInMemoryCache extends Beste\Cache\InMemoryCache
{
public function debugDump(): array
{
return $this->storage->getAll();
}
}
TTL Issues:
$clock = $cache->getClock();
$this->assertInstanceOf(ClockInterface::class, $clock);
Performance Bottlenecks:
Test Isolation:
public function tearDown(): void
{
$this->cache->clear();
}
Laravel Service Provider:
public function register()
{
$this->app->singleton(Beste\Cache\InMemoryCache::class, function () {
return new Beste\Cache\InMemoryCache();
});
}
Clock Customization:
Beste\Clock\SystemClock for production-like behavior in tests:
$cache = new Beste\Cache\InMemoryCache(new SystemClock());
Key Naming:
test_, dev_):
$cache->set('test_user_data', $user, 300);
Laravel Cache Events:
Cache::store('in_memory')->flush();
Benchmarking:
How can I help you explore Laravel packages today?