spiritix/lada-cache
Redis-backed, fully automated query cache for Laravel. Transparently caches Eloquent/Query Builder queries with granular invalidation (rows/tables), scales across Redis/cluster setups, supports include/exclude tables, and integrates with Laravel Debugbar.
Installation:
composer require spiritix/lada-cache
php artisan vendor:publish --provider="Spiritix\LadaCache\LadaCacheServiceProvider"
Enable in .env:
LADA_CACHE_ACTIVE=true
Add Trait to Models:
use Spiritix\LadaCache\Database\LadaCacheTrait;
class User extends Model
{
use LadaCacheTrait;
}
(Best practice: Extend a BaseModel with the trait.)
Verify Redis Connection:
Ensure your config/database.php has a Redis connection named cache (default) or update lada-cache.php to match your Redis connection name.
Run a query and observe automatic caching:
$user = User::find(1); // Automatically cached
Check Debugbar (if enabled) for cache hits/misses.
Transparent Caching:
Cache::remember() calls needed.Granular Invalidation:
users invalidates only the cached users row, not the entire table.Debugging & Monitoring:
php artisan lada-cache:flush # Clear all cache
php artisan lada-cache:disable # Temporarily disable
php artisan lada-cache:enable # Re-enable
Multi-Database Apps:
Configure lada-cache.php to specify which tables/models to cache per connection.
'exclude_tables' => [
'connection1' => ['ignored_table'],
'connection2' => ['another_table'],
],
Bypassing Cache:
Use withoutCache() for freshness-critical queries:
User::where('active', true)->withoutCache()->get();
Custom Redis Connection:
Override the default Redis connection in lada-cache.php:
'redis_connection' => 'custom_redis',
Model-Level Control:
Exclude specific models from caching via config/lada-cache.php:
'exclude_models' => [
'App\Models\UncachedModel',
],
Migrations & Cache:
Lada auto-flushes cache after migrations (via MigrationsEnded event).
Tag-Based Invalidation:
Leverage Redis tags for complex invalidation logic (e.g., invalidate all users with role:admin).
// In a service or observer
Cache::tags(['users:admin'])->flush();
Cache Key Customization: Override cache key generation for specific queries:
User::query()->withCacheKey('custom_prefix:user:{id}')->find(1);
Connection-Specific Caching:
Use DB::connection('mysql')->table(...) to ensure queries use the correct cached connection.
Composite Primary Keys:
lada-cache.php to exclude such tables.Raw SQL Bypasses Cache:
DB::select(), DB::statement(), or raw PDO bypass caching.Third-Party Query Builders:
Spiritix\LadaCache\Database\Query\Builder or wrap queries in withoutCache().Debugbar Conflicts:
LADA_CACHE_DEBUGBAR in .env to avoid errors.LADA_CACHE_DEBUGBAR=false
Cache Key Collisions:
UNION, EXISTS) may generate ambiguous keys.withoutCache() for problematic queries or report to maintainers.Redis Connection Issues:
Pessimistic Locks Bypass Cache:
lockForUpdate()/sharedLock() queries are never cached.withoutCache() explicitly if needed for locked queries.Check Cache Hits/Misses:
CacheMiss or CacheHit entries.Log Invalidation Events:
lada-cache.php:
'log_invalidations' => true,
storage/logs/laravel.log for invalidation events.Verify Cache Keys:
dd() to inspect the cache key for a query:
$query = User::where('active', true);
dd($query->getQuery()->toSql(), $query->getCacheKey());
Test Invalidation:
User::find(1)->update(['name' => 'New']);
// Check if the cached row is invalidated
Redis CLI Inspection:
redis-cli keys "*" # List all keys
redis-cli smembers users:1 # Check row-level tags
Large Payloads:
Complex Joins:
Write-Heavy Workloads:
lada-cache.php to increase TTL or exclude volatile tables.Custom Cache Key Generation:
Override getCacheKey() in your model:
public function getCacheKey()
{
return 'custom:key:' . $this->id;
}
Custom Invalidation Logic: Extend the invalidator:
use Spiritix\LadaCache\Database\Invalidator;
class CustomInvalidator extends Invalidator
{
protected function getTagsForModel($model)
{
return ['custom:tag:' . $model->id];
}
}
Register in AppServiceProvider:
LadaCache::setInvalidator(new CustomInvalidator());
Redis Connection Hooks: Extend Redis connection logic:
LadaCache::extendRedisConnection(function ($connection) {
return Redis::connection($connection)->withTimeout(2.5);
});
Event Listeners:
Listen to cache events (e.g., LadaCacheCached, LadaCacheInvalidated):
use Spiritix\LadaCache\Events\CacheHit;
CacheHit::listen(function ($event) {
Log::debug('Cache hit for:', [$event->query, $event->key]);
});
How can I help you explore Laravel packages today?