Laravel Tutorial · Beyond the Basics · Lesson 24 of 27
Caching
Store expensive results with Cache::remember, choose a cache store (Redis, database, file), invalidate correctly, and use atomic locks.
Cache::remember
The most useful caching call: return the cached value if it exists, otherwise run the closure, store the result for a time, and return it.
$stats = Cache::remember('dashboard:stats', now()->addMinutes(10), fn () => $this->expensiveStats());
Other operations: Cache::get/put/has/forget, increment, rememberForever, flexible (serve stale data while refreshing in the background), and tags on Redis to forget groups of keys. Stores are configured in config/cache.php (redis, database, file, memcached, array for tests).
Invalidate on change: when the underlying data changes, Cache::forget() the key (for example in a model event), or include a version in the key.
Locks (Cache::lock('report', 10)->get(...)) stop two workers from doing the same job at once.
<?php
use Illuminate\Support\Facades\Cache;
$calls = 0;
$expensive = function () use (&$calls) {
$calls++; // pretend this is a slow query or API call
return ['users' => 1200, 'orders' => 3400];
};
$first = Cache::remember('stats', 600, $expensive);
$second = Cache::remember('stats', 600, $expensive);
echo "stats: ", json_encode($second), ", computed $calls time(s)\n";
Cache::forget('stats'); // data changed: invalidate
Cache::remember('stats', 600, $expensive);
echo "after forget, computed $calls time(s)\n";
Cache::put('visits', 0);
foreach (range(1, 5) as $i) {
Cache::increment('visits');
}
echo 'visits: ', Cache::get('visits'), ', missing key default: ', Cache::get('nope', 'default'), "\n";
$lock = Cache::lock('nightly-report', 10);
echo 'first worker gets the lock: ', $lock->get() ? 'yes' : 'no', "\n";
echo 'second worker gets it: ', Cache::lock('nightly-report', 10)->get() ? 'yes' : 'no', "\n";
$lock->release();
echo 'after release: ', Cache::lock('nightly-report', 10)->get() ? 'yes' : 'no', "\n";
Output
stats: {"users":1200,"orders":3400}, computed 1 time(s)
after forget, computed 2 time(s)
visits: 5, missing key default: default
first worker gets the lock: yes
second worker gets it: no
after release: yesRun this on your computer — see “Get Started” for setup.
Test yourself
What does Cache::remember('key', 600, $fn) do on a cache hit?
Runs $fn againReturns the stored value without running $fnDeletes the keyExtends the TTL only
Show answer
Answer: Returns the stored value without running $fn