Generated by boost:update for Boost 2.8, which replaces the pest-testing skill with testing-best-practices and adds infer-conventions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017XYnWFt9pJEwvAmNFN38XD
3.3 KiB
Caching Best Practices
Use Cache::remember() for Cache-Aside Reads
Cache::remember() implements a cache-aside read without a separate truthiness check. It does not prevent concurrent requests from computing the same missing value; use an atomic lock when duplicate computation must be prevented.
The manual version below incorrectly treats valid falsy values, such as false or 0, as cache misses.
Incorrect:
$val = Cache::get('stats');
if (! $val) {
$val = $this->computeStats();
Cache::put('stats', $val, 60);
}
Correct:
$val = Cache::remember('stats', 60, fn () => $this->computeStats());
Consider Cache::flexible() for Stale-While-Revalidate
For frequently read keys, Cache::flexible() can serve stale data during a defined stale period and register a deferred refresh. During an HTTP request, that refresh normally runs after the response; it is not a durable background job. Once the stale period has elapsed, the request recomputes the value synchronously.
Synchronous expiration:
Cache::remember('users', 300, fn () => User::all());
Stale-while-revalidate tradeoff:
Cache::flexible('users', [300, 600], fn () => User::all());
This value is fresh for five minutes and may be served stale until ten minutes after it was cached.
Use Cache::memo() to Avoid Redundant Hits Within an Execution
If the same cache key is read repeatedly during one request or job, memo() decorates a cache store and retains resolved values in memory for that execution.
$settings = Cache::memo()->get('settings');
Repeated reads through the same memoized store avoid additional store lookups. Writes through the memoized store update or invalidate its in-memory values as appropriate.
Use Cache Tags to Invalidate Related Groups
Tags group related entries for invalidation without tracking each key. Cache tags are not supported by the file, dynamodb, or database drivers; confirm support before choosing a store.
Cache::tags(['user-1'])->flush();
Use Cache::add() for Atomic Conditional Writes
add() atomically writes a value only when the key does not already exist.
Incorrect:
if (! Cache::has('lock')) {
Cache::put('lock', true, 10);
}
Correct:
Cache::add('lock', true, 10);
Use Cache::lock() rather than an ordinary cache key when lock ownership and safe release are required.
Use once() for In-Process Memoization
once() memoizes a callback's return value for the current request or job. Calls made from an object instance are scoped to that instance. Unlike Cache::memo(), once() does not read from an external cache store.
public function roles(): Collection
{
return once(fn () => $this->loadRoles());
}
Repeated calls return the memoized result without rerunning the callback. Use once() for repeated computation within one execution. Use Cache::memo() to memoize access to an underlying store that can also persist values across executions.
Configure Failover Cache Stores in Production
The failover driver tries each configured store in order when a store operation throws an exception. It does not consult later stores for an ordinary cache miss, and data is not replicated between stores.
'failover' => ['driver' => 'failover', 'stores' => ['redis', 'database']],