php 45 lines · 5 steps

Tagged cache invalidation in Laravel

A service class caches product and category reads under overlapping tags so related entries can be flushed together precisely.

Explained by highlit
1<?php
2 
3namespace App\Services;
4 
5use App\Models\Product;
6use Illuminate\Support\Facades\Cache;
7 
8class CatalogCache
9{
10 private const TTL = 3600;
11 
12 public function forProduct(int $productId): Product
13 {
14 return Cache::tags(['catalog', "product:{$productId}"])->remember(
15 "product:{$productId}",
16 self::TTL,
17 fn () => Product::with('variants', 'category')->findOrFail($productId)
18 );
19 }
20 
21 public function forCategory(int $categoryId): array
22 {
23 return Cache::tags(['catalog', "category:{$categoryId}"])->remember(
24 "category:{$categoryId}:products",
25 self::TTL,
26 fn () => Product::where('category_id', $categoryId)
27 ->orderBy('name')
28 ->get()
29 ->all()
30 );
31 }
32 
33 public function flushProduct(Product $product): void
34 {
35 Cache::tags([
36 "product:{$product->id}",
37 "category:{$product->category_id}",
38 ])->flush();
39 }
40 
41 public function flushAll(): void
42 {
43 Cache::tags('catalog')->flush();
44 }
45}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Tagging cache entries lets you invalidate groups of related keys without tracking each key by hand.
  2. 2Overlapping tags (a broad one plus specific ones) give you both fine-grained and sweeping invalidation from the same store.
  3. 3Wrapping expensive reads in remember keeps the caching concern in one place instead of scattered across callers.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Tagged cache invalidation in Laravel — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code