rennokki/laravel-eloquent-query-cache
Installation:
composer require rennokki/laravel-eloquent-query-cache
Publish the config (optional):
php artisan vendor:publish --provider="RenokiCo\LaravelEloquentQueryCache\ServiceProvider"
First Use Case: Cache a simple query for 5 minutes:
use RenokiCo\LaravelEloquentQueryCache\Eloquent\Cacheable;
class User extends Model
{
use Cacheable;
}
// In your controller/service:
$users = User::where('active', true)->cacheFor(5)->get();
Where to Look First:
config/eloquent-query-cache.php for configuration options.src/Eloquent/Cacheable.php for the trait implementation details.Basic Caching:
// Cache for 10 minutes
$posts = Post::where('published', true)->cacheFor(10)->get();
// Cache forever (until manually cleared)
$tags = Tag::all()->cacheForever();
Conditional Caching:
// Only cache if the query has no constraints (e.g., `all()`)
$allUsers = User::all()->cacheIfEmpty(300); // 5 minutes
Tag-Based Invalidation:
// Cache with tags for granular invalidation
$products = Product::where('category', 'electronics')
->cacheFor(60, ['electronics', 'inventory'])
->get();
// Later, invalidate by tags
Cache::tags(['electronics'])->flush();
Dependency-Based Invalidation:
// Cache with dependencies (e.g., other models)
$user = User::find(1)
->cacheFor(30, ['user:1'], fn() => User::with('posts')->find(1))
->get();
Integration with Existing Code:
Model::query()->get() calls with cached versions.class UserRepository {
public function getActiveUsers() {
return User::where('active', true)->cacheFor(30)->get();
}
}
Dynamic Cache Keys:
// Use a custom key generator
$users = User::where('role', 'admin')
->cacheFor(60, null, fn() => "admin_users_{$this->tenantId}")
->get();
Caching Relationships:
// Cache eager-loaded relationships
$user = User::with('posts')->find(1)->cacheFor(30)->get();
Partial Caching:
// Cache only specific columns
$user = User::select('id', 'name', 'email')
->cacheFor(10, null, fn() => "user:1:basic")
->first();
Fallback Logic:
// Use cached data if available, otherwise fetch fresh
$data = Cache::remember('users_active', 30, function () {
return User::where('active', true)->get();
});
Testing:
$this->partialMock(Cache::class, 'get');
Cache::shouldReceive('get')->andReturn([]);
Cache Invalidation:
create, update, or delete).// Invalidate after update
$user->update(['name' => 'New Name']);
Cache::tags(['user:'.$user->id])->flush();
Over-Caching:
Memory Leaks:
Model::all()) without pagination.$users = User::paginate(20)->cacheFor(10)->get();
Key Collisions:
"users") for multiple queries.->cacheFor(60, null, fn() => "users_active_{$this->tenantId}")
Relationship Caching:
Configuration Conflicts:
config/eloquent-query-cache.php for defaults:
'default_ttl' => 60, // seconds
'use_tags' => true,
Check Cache Hits/Misses:
'debug' => env('APP_DEBUG', false),
\RenokiCo\LaravelEloquentQueryCache\Cache::debug(true);
Inspect Cache Storage:
Cache::getStore() to check stored keys:
dd(Cache::store()->get('eloquent-query-cache:*'));
Common Errors:
CacheableTrait not found: Ensure the trait is properly used in your model.->toArray() or ->jsonSerialize() if needed.Custom Cache Drivers:
// In ServiceProvider
$this->app->extend('eloquent-query-cache.driver', function ($app) {
return new CustomCacheDriver();
});
Event Listeners:
eloquent.query.cached):
Event::listen('eloquent.query.cached', function ($model, $query, $cacheKey) {
Log::info("Cached query for {$model} with key {$cacheKey}");
});
Middleware:
public function handle($request, Closure $next) {
if ($request->wantsJson()) {
Cache::shouldCacheQueries(true);
}
return $next($request);
}
Testing Helpers:
public function assertCached($model, $cacheKey) {
$this->assertTrue(Cache::has($cacheKey));
}
Performance Tuning:
// High volatility (e.g., stock prices)
->cacheFor(5)
// Low volatility (e.g., static pages)
->cacheForever()
How can I help you explore Laravel packages today?