Cache::get
Reads a value from the cache, returning null or a supplied default when the key is not present.
Cache::get(string|array $key, mixed $default = null): mixed- Added in Laravel 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$$key | string|array | The cache key to read. An array of keys performs a multi-get and returns an array keyed by the requested keys. |
$$defaultoptional | mixed= null | Value returned on a miss. A Closure is invoked only on a miss, so an expensive fallback costs nothing on a hit. |
Return value
mixedThe cached value, or the default (a closure default is invoked) when the key is absent. Passing an array of keys returns an array keyed by those keys.
Errors
Nothing is thrown for a missing key. An unknown store name passed to Cache::store() raises InvalidArgumentException.
Changelog
- PHP 5.8Cache TTLs moved from minutes to seconds across the whole cache API, which changes what a value written by older code expires at.
Cache::get is the plain read. It asks the configured store for a key and hands back whatever was stored, deserialized. A miss is not an error: you get null, or the second argument if you passed one.
When to reach for it
Use it when the cached value is genuinely optional — a feature flag, a warmed-up count, a value another process writes. If your code's next move on a miss is "compute it and store it", you want Cache::remember instead; hand-rolling get-then-put duplicates logic and widens the race window.
The default may be a closure. It is only invoked on a miss, which lets you defer a database round trip:
$plan = Cache::get("plan:$id", fn () => Plan::find($id));Note that this does not write the result back — it is a fallback, not a warm-up.
What trips people up
You cannot distinguish "key absent" from "key holds null" through the return value. Cache::has() also reports false for a stored null, so a genuinely nullable value should be wrapped — store an array or a sentinel string rather than bare null.
Passing an array of keys switches the method to a multi-get, returning an array with null for every key that missed. One round trip instead of N on Redis and Memcached.
Example
<?php
use Illuminate\Support\Facades\Cache;
// Simple read: null when the key was never written.
var_dump(Cache::get('report:daily'));
// Literal default on a miss.
echo Cache::get('theme', 'light'), PHP_EOL;
// Closure default: only evaluated when the key is missing,
// and the result is NOT written back to the cache.
$plan = Cache::get('plan:42', function () {
return ['name' => 'free', 'seats' => 1];
});
print_r($plan);
// Array of keys performs a multi-get.
print_r(Cache::get(['theme', 'locale']));When to use it
- Read a feature flag that a background job refreshes, falling back to the off state.
- Fetch a precomputed dashboard total and render a placeholder when the warmer has not run yet.
- Pull several rate-limit counters in one round trip by passing an array of keys.
Frequently asked questions
Why does Cache::get return null when I know I stored a value?
Either the key expired, or you are reading from a different store or cache prefix than the one you wrote to. Confirm CACHE_STORE is the same in the writing process (a queue worker or Artisan command often has its own environment) and remember that a queue worker keeps its config until it is restarted.
Does the default value get written to the cache?
No. The default, closure or not, is returned but never stored, so the next read misses again. Use Cache::remember when you want the computed value persisted.
Can I get several cache keys in one call?
Yes, pass an array of keys and you get back an array keyed by those keys, with null for each miss. On Redis and Memcached this is one network round trip instead of one per key.
More examples
Telling a miss apart from a stored null
The first three lines show the ambiguity: a deliberately cached null is indistinguishable from a key that was never written, and has() agrees with the miss. Wrapping the value in a one-key array makes the outer null mean "miss" and the inner null mean "no nickname", which is what negative caching needs.
<?php
use Illuminate\Support\Facades\Cache;
Cache::put('user:7:nickname', null, 600);
// Both of these look identical from the outside.
var_dump(Cache::get('user:7:nickname')); // NULL (stored null)
var_dump(Cache::get('user:99:nickname')); // NULL (never written)
var_dump(Cache::has('user:7:nickname')); // bool(false)
// Wrap the value so "we looked and it was null" is representable.
Cache::put('user:7:nickname', ['value' => null], 600);
$cached = Cache::get('user:7:nickname');
var_dump($cached !== null); // bool(true) -> we have an answer
var_dump($cached['value']); // NULL -> the answer is nullReading a specific store and using a multi-get
store() selects an entry from the stores array in config/cache.php. Passing an array of keys issues a single MGET against Redis rather than three separate reads; the third key is absent, so its slot holds null while keeping its position in the returned array.
<?php
use Illuminate\Support\Facades\Cache;
// Read from a named store instead of the default one.
$value = Cache::store('redis')->get('queue:depth', 0);
echo "queue depth: {$value}", PHP_EOL;
// One round trip for several keys. Misses come back as null.
$counters = Cache::store('redis')->get([
'hits:2024-05-01',
'hits:2024-05-02',
'hits:2024-05-03',
]);
print_r($counters);
// Expected shape:
// Array
// (
// [hits:2024-05-01] => 1204
// [hits:2024-05-02] => 980
// [hits:2024-05-03] =>
// )
Discussion