Introduction to Cache in Laravel

- Andrés Cruz

En español
Introduction to Cache in Laravel

Este material forma parte de mi curso y libro completo; puedes adquirirlos desde el apartado de libros y/o cursos Curso y libro Laravel 11 con Tailwind Vue 3, introducción a Jetstream Livewire e Inerta desde cero - 2024.

In any system, it is essential to manage the management of resources to improve the overall performance of the system; one of the most important points in a system is about the types of requests that are repeated consecutively; A good example of this is a rest resource from a rest api; For example, a resource that always returns the same type of list is a good candidate to improve its performance; to analyze this point, suppose we have a resource that returns 10,000 records or more:

app\Http\Controllers\Api\PostController.php
class PostController extends Controller
{
    public function all(): JsonResponse
    {
        return  response()->json(Post::get());
    }
}

We can improve its performance by storing this data in cache; In Laravel, cache management is a crucial functionality to improve the performance of our web applications. Laravel offers support for multiple caching systems, including in-memory, disk, database, and even systems like Redis. This allows us to temporarily store data that is frequently consumed to speed up the response time of our applications and with this, consume less resources.

In short, caching data reduces the number of times a repeated request needs to be processed and optimizes application response time, since cached data can be quickly retrieved without having to run the process that handles it. generate said data; traditionally, it would be the access to the database, but it can be anything else like HTML.

Basic use of the cache

With the cache in Laravel, we have different methods and options that we can use to adapt it to different schemes; let's see the main ones:

  • get()
  • has()
  • put()
  • putMany()
  • add()
  • pull()
  • many()
  • remember()
  • rememberForever()
  • increment()
  • decrement()
  • forever()
  • forget()
  • flush()

All of these methods are available through the cache Facade; all these cache methods have in common that they receive a key (with the exception of the putMany() method), in order to access the cache; for example, if you want to save the detail of a post, this key can be post or post_detail for example, if you want a list of posts, it can be posts or posts_index; and using this key, is that we can make a reference to the cache.

Cache::get()

The get() method is used to retrieve items from the cache. If the item does not exist in the cache, a null value will be returned:

$value = Cache::get('key');

Optionally, a second argument can be passed that specifies the default value to be used if the element does not exist:

$value = Cache::get('key', 'default');

Cache::has()

The has() method is used to determine if an item exists in the cache; returns false if the value does not exist and true otherwise:

Cache::has('key');

Cache::put()

The put() method accepts three parameters:

  1. key/key.
  2. Cache duration.
  3. The data to be cached.

Cache::put(key, data, duration)

For example:

Cache::put('key', 'value', $seconds = 10);
// Cache::put('key', 'value', now()->addMinutes(10));

Cache::putMany()

The putMany() method stores an array of data in the cache, otherwise it has the same parameters as the put() function except for the key:

Cache::putMany(Post::all(), now()->addMinutes(10));

Cache::add()

The add() method only adds the item to the cache if it doesn't already exist in the cache store. The method will return true if the item is actually added to the cache, otherwise it returns false:

Cache::add('key', 'value', now()->addMinutes(10));

Cache::pull()

The pull() method can be used if you need to retrieve an item from the cache and then remove it; like the get() method, it will return null if the item doesn't exist in the cache:

$value = Cache::pull('key');

Cache::many()

The many() method is used to retrieve multiple data based on an array of keys:

const $keys = [
 'post_1',
 'post_2',
 'post_3',
 ***
];
cache::many(keys);

Cache::remember()

  1. Many times you may want to retrieve an item from the cache, but also store a default value if the requested item does not exist. and for this we can use the remember() method that accepts three parameters:
  2. The key.
    cache duration
  3. The data to retrieve if the same is not found.
Cache::remember('posts', now()->addMinutes(10), function(){
 return Post::all();
});

In the above script, the function returns all posts (Post::all()) if the cached data does not exist.

cache::rememberForever()

You can use the rememberForever() method to retrieve an item from the cache or store it forever (there is no parameter to pass the cache lifetime) if it doesn't exist:

$value = Cache::rememberForever('posts', function () {
 return Post::all();
});

Increasing or decreasing cached values

You can change the values

is a cached integer value using the increment and decrement methods, respectively:

Cache::increment('key'); //$value = 1
Cache::increment('key', $value);
Cache::decrement('key'); //$value = 1
Cache::decrement('key', $value);
Cache::forever()

The forever() method stores the data in the cache forever without specifying any duration:

Cache::forever('key', 'value');

Cache::forget()

The forget() method removes an item from the cache with a specified key parameter:

Cache::forget('key');

Cache::flush()

This method clears all items from the cache:

Cache::flush();

Case study

There are many approaches that we can use when using the cache in Laravel; one of the classics is, when making a query we do the following steps:

  • We check if they already exist stored in the cache.
  • If they exist, the cached data is returned.
  • If they don't exist, the database is queried and with the response, we use it both to set in the cache and as part of the response.

With this in mind, we can change the all() function seen earlier in our Rest API to look like:

app\Http\Controllers\Api\PostController.php

class PostController extends Controller
{
    public function all(): JsonResponse
    {
        if (Cache::has('posts_index2')) {
            return response()->json(Cache::get('posts_index2'));
        } else {
            $posts = Post::get();
            Cache::put('posts_index2', $posts);
            return  response()->json($posts);
        }
    }
}

Another important factor is that, with the cache system that we defined for the details of the posts, we are not avoiding the connection to the database which is implicit in the route:

use Illuminate\Support\Facades\Cache;
***
class BlogController extends Controller
{
    public function show(Post $post): String // Post::find(<PK>)
    ***

To avoid this, you can change the route type and do the search manually only when the cache does not exist:

use Illuminate\Support\Facades\Cache;
***
class BlogController extends Controller
{
    public function show(int $id /*slug*/): String
    {

        if (Cache::has('post_show_' . $id)) {
            return Cache::get('post_show_' . $id);
        } else {
            $post = Post::find($id);
            $cacheView = view('blog.show', compact('post'))->render();
            Cache::put('post_show_' . $post->id, $cacheView);
            return $cacheView;
        }

        // return view('blog.show', compact('post'));
    }
}

Finally, we can also use the cache() helper function instead of Facade for all the previous methods, for example:

cache()->has('post_show_'.$post->id);

Controller types

In Laravel, there are different types of controllers available, among them are:

File

The file type driver saves the cache to files on the file system; this is the default scheme used in Laravel and the generated encrypted file is located in storage/framework/; It does not require additional configurations and we can use it both in development and in production.

CACHE_STORE=file

Database

The database driver stores the cache in a database table; this type requires additional configurations, to generate the table:

$ php artisan cache:table

For most of the cases, this scheme is not ideal since, with the use of the cache, we usually want to free up database resources and using the driver for the database cache, we could generate a neck of bottle.

CACHE_STORE=database

Memcached

Memcached type driver stores the cache on a Memcached cache server; Memcached is a high-performance memory-based data store; therefore, in order to use it, you need to install an additional package.

CACHE_STORE=memcached

Redis

The Redis driver stores the cache in a database engine called Redis; Redis is one of the most popular configurations in Laravel as it is very fast; although, it requires installation and configuration of a program external to the project in Laravel.

CACHE_STORE=redis

Array

The Array controller stores data in an array in PHP and does not require installation of additional programs.

CACHE_STORE=array

These settings are found in the file:

config\cache.php

'default' => env('CACHE_STORE', 'file'),

/*
|--------------------------------------------------------------------------
| Cache Stores
|--------------------------------------------------------------------------
|
| Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
| Supported drivers: "apc", "array", "database", "file",
|         "memcached", "redis", "dynamodb", "octane", "null"
|
*/
***

And at the environment variables:

.env

CACHE_STORE=file

Laravel: Error Class "Redis" Not Found Error

When we want to use Redis in a new Laravel application, the following error may appear:

Class "Redis" Not Found Error

Why does this error occur?

The reason for this error is usually a missing Composer package or a missing Redis installation. In both cases, it appears once you try to use Redis on your system for the following:

CACHE_DRIVER=redis

Based on this, one of the following situations may occur.

Missing composer package

This is the most common reason for having this error. To fix it, run the following command:

composer require predis/predis

And once the package is installed, you should be able to use Redis.

Redis installation missing

If you have installed the package, but the error is still there, you may need to install Redis. To install Redis, follow the instructions on the official Redis website.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.