Cache::get

Reads a value from the cache, returning null or a supplied default when the key is not present.

Signature
Cache::get(string|array $key, mixed $default = null): mixed
  • Added in Laravel 4.0

Parameters

ParameterTypeDescription
$$keystring|arrayThe cache key to read. An array of keys performs a multi-get and returns an array keyed by the requested keys.
$$defaultoptionalmixed= nullValue 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

Example · php
<?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.

Example · php
<?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 null

Reading 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.

Example · php
<?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

  • Be the first to comment on this lesson.