Installation:
composer require rinvex/laravel-cacheable
Publish the config (optional):
php artisan vendor:publish --provider="Rinvex\Cacheable\CacheableServiceProvider"
Enable Caching for a Model:
Add the Cacheable trait to your Eloquent model:
use Rinvex\Cacheable\Cacheable;
class Post extends Model
{
use Cacheable;
}
First Use Case: Cache a query result for 5 minutes:
$posts = Post::cacheFor(5)->get(); // Automatically caches the query
Granular Caching: Cache specific queries with conditions:
$activePosts = Post::where('status', 'published')
->cacheFor(10)
->get();
Fluent Integration: Chain caching with other query methods:
$recentPosts = Post::orderBy('created_at', 'desc')
->take(10)
->cacheFor(15)
->get();
Dynamic Cache Keys:
Leverage query parameters (e.g., where, orderBy) to auto-generate cache keys:
// Cache key: `posts_status_published_order_created_at_desc_limit_10`
Post::where('status', 'published')
->orderBy('created_at', 'desc')
->take(10)
->cacheFor(30)
->get();
Tag-Based Invalidation: Cache with tags for bulk invalidation:
// Cache with tags
Post::cacheFor(60, ['posts', 'published'])
->where('status', 'published')
->get();
// Later, invalidate by tag
Cache::tags(['posts'])->flush();
Conditional Caching:
Use cacheWhen for dynamic caching logic:
$posts = Post::cacheWhen(
fn() => request()->has('cache'),
30
)->get();
Custom Cache Drivers:
Override the default driver in config/cacheable.php:
'driver' => 'redis',
Model-Level Defaults: Set defaults in the model:
protected $cacheable = [
'enabled' => true,
'default_seconds' => 60,
'tags' => ['posts'],
];
Cache Events:
Listen for cache events (e.g., CacheableCached, CacheableMissed):
Cacheable::extend(function ($model) {
Cacheable::onCached(function ($model, $key, $value) {
// Log cache hits
});
});
Fallback to Database:
Use cacheFallback to fetch from DB if cache misses:
$posts = Post::cacheFallback()->cacheFor(60)->get();
Key Collisions:
cacheKey to manually specify a unique key:
Post::cacheKey('custom_key')->cacheFor(60)->get();
Tag Overhead:
['posts', 'published']).TTL Misconfiguration:
cacheFor(0) or negative values may cause unexpected behavior.protected function getCacheTtl(): int
{
return max(1, $this->cacheable['default_seconds'] ?? 60);
}
Eager Loading Quirks:
with().load() after retrieval.Database vs. Cache Staleness:
Inspect Cache Keys: Dump the generated key to verify:
$key = Post::where('status', 'published')->cacheKey();
dd($key); // Debug the key structure
Check Cache Contents:
Use Laravel’s Cache::get() to verify stored data:
dd(Cache::get($key));
Log Cache Events: Enable logging for cache hits/misses:
Cacheable::onCached(fn($model, $key, $value) => Log::debug("Cached: $key"));
Cacheable::onMissed(fn($model, $key) => Log::debug("Missed: $key"));
Custom Key Generators:
Override getCacheKey() in your model:
public function getCacheKey(): string
{
return "custom_prefix_" . parent::getCacheKey();
}
Dynamic TTL: Use a closure for dynamic TTLs:
Post::cacheFor(fn() => request()->wantsJson() ? 300 : 60)->get();
Pre-Caching:
Pre-cache data during model events (e.g., retrieved):
Post::retrieved(function ($post) {
if (!$post->fresh) {
$post->freshTimestamp();
$post->cacheFor(300)->save();
}
});
Fallback Logic:
Extend CacheableFallback to customize fallback behavior:
Cacheable::extend(function ($model) {
$model->setCacheFallback(function () {
return $model->newQuery()->with('relationship')->get();
});
});
spatie/laravel-query-builder-cachingcacheable-eloquent (if available).How can I help you explore Laravel packages today?