How caching query can be done for better performance in Laravel

Caching is used to have better performance on database queries. In this post, we will use caching functionality of laravel on eloquoent queries. 

Suppose, there is relation of author has many books. Now with caching we can make queries in authors table such that it fetches number of books once and then on subsequent requests query will not touch the database. Hence it will also improve performance of query to a large extent. 

So, following snippets can be followed to achieve this result step by step. 

Step 01: Use this post to create migration schema and seed data for author and book table. BookController also needs to be created.

Step 02: In BookController, adding authorBooks() method fetching all authors from database with Author model ( sortByDesc is used to sort the result by books_count )

function authorBooks() {
    $authors = Author::get()->sortByDesc('books_count');
    return view( 'author_books', compact('authors'));
}

Step 03: We create blade file author_books.blade.php inside resources/views and add following code 

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title> Caching </title>

    <!-- Scripts -->

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div id="app">

        <main class="py-4">
            <table>
            @foreach( $authors as $author )
                <tr>
                    <td>{!! $author->name.':' !!} </td>
                    <td>{!! 'Count:'. $author->books_count.'  
'
!!}</td>
</tr> @endforeach <table> </main> </div> </body> </html>

Step 04: Creating accessor method in Author.php model like below

function getBooksCountAttribute() { 
    return $this->books->count();
}

Step 05: Installing laravel debugbar with following artisan command and making sure value of APP_DEBUG is set to true inside .env file

composer require barryvdh/laravel-debugbar

Step 06: Defining route for authorBooks() in web.php 

Route::get('/author_books', [BookController::class, 'authorBooks']);

Now if we run this url http://localhost:8000/author_books in browser we will see list of author and their book count will show in descending order. 

Moreover, in debugbar we will see following results 

1. views (1)
2. Queries (11)
3. Query execution time (13.7ms)
4. Models (110) ( Inside models tab of debugbar, it shows book and author model are being used 100 and 10 times respectively. )
5. Memory usage (20MB)
6. Time spent loading data to memory (277ms) 

Step 07: Now if we use caching snippet will be like below from in accessor method from step 04

function getBooksCountAttribute() {

    Cache::remember( 'author-books-'.$this->id, 60*60 , function(){
        return $this->books->count();
    });

    return Cache::get('author-books-'.$this->id);
}

Code above used laravel caching method remember() which takes three parameters ( name of cache - unique value, duration of existence of cache in seconds and lastly closure - returns the count of books for a particular author ). 

We will need to use get() method of Cache facada so that it returns particular key related cache value in view file. Otherwise it will show empty result there. 

Now if we refresh the browser like above, we will see some drasic changes in terms of number of queries and models being used and its execution time 

1. views (1)
2. Queries (1)
3. Query execution time (5.7ms)
4. Models (10) ( Inside models tab of debugbar, it shows only author model is used  this time )
5. Memory usage (20MB)
6. Time spent loading data to memory (252ms) 

So, number of queries and models are being used 1 and 10 only respectively which is a great performance boost and it will stay like this for an hour ( 60*60 cache existing time ). This two stats were significantly higher for previous code without caching. Another important factor is exexution time of queries - 5.7ms which is like twice as fast than previous scenario. 

Above all we are able to cache database queries to achieve less database access and faster serving of page with laravel's caching feature.