7 min read

Everything you need to learn about Cache in Laravel

Within Laravel applications, the cache is the act of transparently storing data for future use in an attempt to make applications run faster.

Within Laravel applications, the cache is the act of transparently storing data for future use in an attempt to make applications run faster.

You can say that a cache looks like a session. You pretty much use them in the same way, since you need to provide a key to store them.

Of course, there are differences, otherwise, there wouldn’t be two separate functions. Sessions are used to store data between page requests while a cache is used to cache data per application. Therefore, you usually store stuff like database queries and API calls in your cache.

Configuring Cache

The cache configuration file is stored inside the /config/cache.php file, where you will find a couple of important settings that you can change up. I do recommend you to create an environment variable rather than changing the default value setting.

The most important setting is the default, since you’re going to set the default cache driver.

Before we continue, let’s have a look at the different cache driver options.

File

The first driver is the file driver, which is also the default driver. The file driver will create a new encrypted file per cache in /storage/framework/cache directory.

Keep in mind that the key will be encrypted, even if you try to retrieve content from your cache.

It’s also recommended to use the file driver for development since it is faster than adding your cache to the database.

Array

The second available driver is the array driver. The array driver is just a ‘simple’ array where your cache will be stored. The advantage of using the array driver is the fact that you don’t need to configure a driver.

CACHE_DRIVER=array

Database

The third available driver is the database driver. The database driver will store your cache in memory for the current PHP process.

To use the database driver, you got to make sure that you create a database table through artisan.

php artisan cache:table

There is a huge downside to storing your cache in the database. The database driver can be overloaded when you got a ton of cache on your site. In my personal opinion, I don’t recommend using the database driver in real-life examples.

CACHE_DRIVER=database

Redis & Memcached

Redis and Memcached are both more complex drivers than the previous drivers. The Redis driver uses an in-memory-based caching technology, while Memcached does the same, but it requires a bit more server maintenance.

CACHE_DRIVER=redis
CACHE_DRIVER=memcached

How to access your Cache

There are a few different ways to access your cache. The first option is through the Cache Facade.

Cache::get(‘users’);

The second option is by getting an instance from the container.

Route::get(‘users’), function(Illuminate\Contracts\Cache\Repository $cache) {
	return $cache->get(‘users’);
});

The last available option is through the global cache() helper.

$users = cache()->get(‘users’);

Available Methods

There is a couple of method that you could use when working with cache, which we will cover down below.

get($key, $fallbackValue)

The get() method is used to pull values for any given key.

Cache::get('users');

pull($key, $fallbackValue)

The pull() method is exactly the same as the get() method, except it removes the cached value after retrieving it.

Cache::pull('users');

put($key, $value, $secondsOrExpiration)

The put method will set the value of the specified key for a given number of seconds.

Cache::put(‘user’, ‘Code With Dary’, now()->addDay());

add($key, $value)

The add() method is similar to the put() method but if the value already exists in the cache, it won’t set it. Keep in mind that it will also return a Boolean indicating whether or not the value was added.

Cache::add(‘user’, 'Code With Dary');

forever($key, $value)

The forever() method saves a value to the cache for a specific key. It is similar to the put() method, except the value will never expire since you won’t set the expiration time.

Cache::forever(user, 'Dary');

has($key)

The has() method will check whether or not there’s a value at the provided key. It will return a true if the value exists, and false if the value does not exist.

if(Cache::has(user)) {
    dd('Cache exists');
}

increment($key, $amount)

The increment() method speaks for itself. It will increase the value in the cache. If there is no value given, it will treat the value as it was a 0.

Cache::increment(‘user’, 1);

decrement($key, $amount)

The decrement() method also speaks for itself. It will decrease the value in the cache. If there is no value given, it will treat the value as it was a 0.

Cache::decrement('user', 1);

forget($key)

The forget() method removes a previously set cache value.

Cache::forget('user');

flush()

The flush() method removes every cache value, even those set by the framework itself.

Cache::flush();

Example

I do not like storing cache in the database so instead of showing you that, let’s create a simple example where we’re going to store 1000 posts inside the cache, so we don’t need to grab the values from the database every single time we try to find all posts.

Let’s start by pulling in the authentication scaffolding.

composer require laravel/breeze –dev
php artisan breeze:install
php artisan migrate
npm install
npm run dev

We need to make sure that we create a Post model, factory, migration, and resource controller.

php artisan make:model Post -fmr

Let’s define the posts migration in the create_posts_table.php file:

public function up()
{
    Schema::create('posts', function (Blueprint $table){
        $table->increments('id');
        $table->string('title');
        $table->longText('description');
        $table->timestamps();
        $table->unsignedBigInteger('user_id');
        $table->foreign('user_id')->references('id')->on('users');
    });
}

The factory inside PostFactory.php will be set as follows.

public function definition()
{
    return [
        'user_id' => 1,
        'title' => $this->faker->sentence(),
        'description' => $this->faker->paragraph()
    ];
}

Before you can run tinker to run your factory, you got to make sure that you migrate your tables and create a new user, since user_id is already been set to 1.

php artisan tinker

Here, we got to make sure that we call our model, chain the count method of and pass in an integer of the number of rows we’d like to create, and chain the create method to finish it off.

App\Models\Post:factory()->count(1000)->create();

If you added the same code as I showed you above, you should have 1000 new rows inside your database. We got to make sure that we have an event and listener setup because it will fetch data from Laravel’s cache.

php artisan make:event PostCreated
php artisan make:listener PostCacheListener

Let’s change up the handle() method inside the PostCacheListener.php file.

public function handle($event)
{
    Cache::forget('posts');

    Cache::forever('posts', Post::all());
}

We got to make sure that we remove the cache, even when it hasn’t been set. Then, we got to make sure that we create a new cache which will last forever. The values will be grabbed from the Post model.

We got to make sure that we hook our event into our model, which can easily be done with the property $dispatchesEvents in the Post model.

protected $dispatchesEvents = [
    'created' => PostCreated::class
];

When using Events and Listeners, you got to make sure that you register them inside the EventServiceProvider.php file, in the property protected $listen.

protected $listen = [
    Registered::class => [
        SendEmailVerificationNotification::class,
    ],
    PostCreated::class => [
        PostCacheListener::class
    ]
];

We’re almost done. We got to make sure that we dispatch the event, then get all posts and put it inside the cache inside our PostController.php file.

public function index()
{
    Event::dispatch(new PostCreated());

    $posts = cache('posts', function () {
        return Post::get();
    });

    return view('index', $posts);
}

The last step if defining the /blog endpoint inside the /routes/web.php file and creating a new folder inside the /resources/views/ folder, called /blog, and add a new file called /index.blade.php in there.

Route::get('/', [PagesController::class, 'index']);
Route::get('/blog', [PostController::class, 'index']);

If we navigate to the browser and change our endpoint to /blog, the /blog/index.blade.php file is being called, but the most important thing is the cache folder that has been created inside the /storage/framework/cache/data folder.

Right here, you’ll find a big JSON file which holds all posts inside that me as the user, has fetched.