Installation:
composer require mostafaznv/laracache
Publish Config (optional):
php artisan vendor:publish --provider="Mostafaznv\Laracache\LaracacheServiceProvider"
cache.driver in .env)config/laracache.php)created, updated, deleted)First Use Case:
Cache a model's find() or first() query by adding the Cacheable trait to your model:
use Mostafaznv\Laracache\Traits\Cacheable;
class User extends Model
{
use Cacheable;
protected $cacheEntity = [
'name' => 'user:123', // Dynamic key (use `{id}` for model ID)
'ttl' => 60, // 60 seconds
];
}
User::find(123) or User::first(). The package auto-caches results on retrieved events.Dynamic Cache Keys:
Use placeholders like {id}, {slug}, or {email} in $cacheEntity['name']:
protected $cacheEntity = [
'name' => 'user:{email}:profile',
'ttl' => 300,
];
user:john@example.com:profile for User::findByEmail('john@example.com').Conditional Caching:
Override getCacheKey() to dynamically adjust keys/TTL:
public function getCacheKey()
{
if ($this->isPremium()) {
return ['name' => 'user:premium:{id}', 'ttl' => 86400];
}
return $this->cacheEntity;
}
Bulk Operations:
Cache collections with CacheableCollection trait:
class UserCollection extends Collection
{
use \Mostafaznv\Laracache\Traits\CacheableCollection;
protected $cacheEntity = [
'name' => 'users:active',
'ttl' => 1800,
];
}
Event-Based Invalidation: Extend cache invalidation to custom events:
// In a service or observer
event(new UserProfileUpdated($user));
// In User model
protected static function getCacheEvents()
{
return [
'created', 'updated', 'deleted',
'user.profile.updated', // Custom event
];
}
Fallback Logic:
Use shouldCache() to skip caching for specific cases:
protected function shouldCache()
{
return !request()->has('nocache');
}
public function toArray($request)
{
return Cache::remember("user:{$this->id}:api", now()->addMinutes(5), function() {
return parent::toArray($request);
});
}
$user = Cache::remember("user:{$id}:job:{$jobId}", now()->addHours(1), function() use ($id) {
return User::find($id);
});
Cache::shouldReceive('get')->andReturn($mockedUser);
Key Collisions:
user:{id} vs. user:{email}) may cause unintended cache hits.'name' => 'user.by_id:{id}', 'user.by_email:{email}'
TTL Granularity:
getCacheTTL() to dynamically adjust:
protected function getCacheTTL()
{
return $this->isActive() ? 3600 : 60; // 1h for active, 1m for inactive
}
Event Hooks:
deleted in getCacheEvents() leaves orphaned cache entries.protected static function getCacheEvents()
{
return ['created', 'updated', 'deleted'];
}
Memory Leaks:
{timestamp}).'name' => 'user:{id}:{timestamp}', // Risky!
'name' => 'user:{id}', // Safer
Race Conditions:
created/updated events may overwrite cache.Cache::lock() for critical sections:
Cache::lock("user:{$id}:update", 5)->block(function() {
// Safe update logic
});
Cache Inspection: Use Tinker to inspect cached keys:
php artisan tinker
>>> Cache::keys('user:*')->contains('user:123');
Logging:
Enable debug mode in config/laracache.php:
'debug' => env('APP_DEBUG', false),
storage/logs/laracache.log.Manual Invalidation: Force-invalidate a cache key:
Cache::forget('user:123');
Custom Cache Drivers:
Bind a custom driver in AppServiceProvider:
Cache::extend('redis_cluster', function() {
return Cache::repository(new RedisClusterStore());
});
Then configure in .env:
CACHE_DRIVER=redis_cluster
Cache Tags:
Add tag-based invalidation (requires illuminate/cache v8.50+):
protected $cacheTags = ['users', 'premium_users'];
Invalidate by tag:
Cache::tags(['users'])->flush();
Cache Warmers: Pre-load caches during deployment:
php artisan cache:warm
app/Console/Kernel.php:
protected function warmCache()
{
Cache::put('homepage', Homepage::with('stats')->first());
}
Cache Versioning: Append a version to keys to invalidate all caches on config changes:
'name' => 'user:{id}:v' . config('cache.version'),
How can I help you explore Laravel packages today?