| name | laravel-caching-strategies |
| description | Best practices for Laravel caching including cache patterns, tags, atomic locks, flexible cache, and cache invalidation strategies. |
Laravel Caching Strategies
Core Cache Patterns
use Illuminate\Support\Facades\Cache;
$users = Cache::remember('users:active', now()->addMinutes(30), function () {
return User::where('active', true)->get();
});
$settings = Cache::rememberForever('app:settings', function () {
return Setting::all()->pluck('value', 'key');
});
$stats = Cache::flexible('dashboard:stats', [300, 900], function () {
return DashboardStats::calculate();
});
Cache::put('key', $value, now()->addHours(1));
$value = Cache::get('key', 'default');
Cache::forget('key');
$settings = Setting::all();
Cache Tags for Grouped Invalidation
Cache::tags(['posts', 'users'])->put("user:{$userId}:posts", $posts, 3600);
Cache::tags(['posts'])->put("post:{$postId}", $post, 3600);
Cache::tags(['users'])->put("user:{$userId}:profile", $profile, 3600);
Cache::tags(['posts'])->flush();
$posts = Cache::tags(['posts', 'users'])->get("user:{$userId}:posts");
Atomic Locks
use Illuminate\Support\Facades\Cache;
$lock = Cache::lock('processing:order:' . $orderId, 10);
if ($lock->get()) {
try {
$this->processOrder($orderId);
} finally {
$lock->release();
}
}
$lock = Cache::lock('report:generate', 30);
$lock->block(5, function () {
$this->generateReport();
});
$lock = Cache::lock('deployment', 120);
if ($lock->get()) {
$owner = $lock->owner();
}
Cache::restoreLock('deployment', $owner)->release();
$lock->get();
$this->doWork();
Cache Memoization
use Illuminate\Support\Facades\Cache;
$config = Cache::memo('app:config', function () {
return Config::loadFromDatabase();
});
$config = Cache::memo('app:config', fn () => Config::loadFromDatabase());
Model Caching Patterns
class Product extends Model
{
public static function findCached(int $id): ?self
{
return Cache::remember(
"product:{$id}",
now()->addHour(),
fn () => static::find($id)
);
}
protected static function booted(): void
{
static::saved(function (Product $product) {
Cache::forget("product:{$product->id}");
Cache::tags(['products'])->flush();
});
static::deleted(function (Product $product) {
Cache::forget("product:{$product->id}");
Cache::tags(['products'])->flush();
});
}
}
class ProductService
{
public function getFeatured(): Collection
{
return Cache::tags(['products'])->remember(
'products:featured',
now()->addMinutes(30),
fn () => Product::where('featured', true)->with('category')->get()
);
}
}
Cache Key Conventions
"user:{$userId}:profile"
"post:{$postId}:comments:page:{$page}"
"tenant:{$tenantId}:settings"
"api:github:repos:{$username}"
"report:daily:{$date}"
"v2:user:{$userId}:profile"
"data"
"user"
"temp"
"cache_1"
Common Pitfalls
$user = Cache::remember("user:{$id}", 3600, fn () => User::find($id));
$user = Cache::remember("user:{$id}", 3600, function () use ($id) {
return User::find($id) ?? new NullUser();
});
Cache::forever('products:all', Product::all());
Cache::remember('products:all', now()->addMinutes(15), fn () => Product::all());
Cache::remember('user:count', 3600, fn () => User::count());
Cache::remember('dashboard:analytics', 3600, function () {
return DB::table('orders')
->selectRaw('DATE(created_at) as date, SUM(total) as revenue')
->groupByRaw('DATE(created_at)')
->orderBy('date')
->get();
});
Checklist