Upgrade your Laravel App with Query Result Caching

Upgrade your Laravel App with Query Result Caching

As Laravel developers, we're always on the lookout for ways to optimize our applications. One often overlooked technique is query result caching. In this post, we'll explore how to implement query result caching in Laravel to significantly speed up repeated database calls.

What is Query Result Caching?

Query result caching is a technique where we store the results of database queries in memory for a specified period. This allows us to retrieve the data quickly on subsequent requests without hitting the database, resulting in faster response times and reduced database load.

Implementing Query Result Caching in Laravel

Laravel makes it easy to implement query result caching. Here's a basic example:

use Illuminate\Support\Facades\Cache;

class SettingsRepository
{
    public function getAllSettings()
    {
        return Cache::remember('all_settings', 86400, function () {
            return Setting::all();
        });
    }

    public function updateSetting($key, $value)
    {
        Setting::where('key', $key)->update(['value' => $value]);
        Cache::forget('all_settings');
    }
}

Let's break down what's happening here:

  1. We use Cache::remember() to store the result of Setting::all() for 24 hours (86400 seconds).
  2. If the cache exists, it's returned immediately without querying the database.
  3. If the cache doesn't exist or has expired, the query is executed, and the result is stored in the cache before being returned.
  4. When a setting is updated, we invalidate the cache using Cache::forget().

Benefits of Query Result Caching

  1. Improved Performance: Cached results are returned much faster than database queries.
  2. Reduced Database Load: Fewer queries mean less strain on your database server.
  3. Scalability: Your application can handle more traffic without proportionally increasing database load.
  4. Consistency: All requests within the cache period receive the same data, which can be beneficial in certain scenarios.

Real-Life Example: E-commerce Category Navigation

Let's consider a real-world scenario where query result caching can make a significant impact: the category navigation of an e-commerce site.

use Illuminate\Support\Facades\Cache;

class CategoryController extends Controller
{
    public function getNavigationTree()
    {
        return Cache::remember('category_navigation', 3600, function () {
            return $this->buildNavigationTree();
        });
    }

    private function buildNavigationTree()
    {
        $categories = Category::with('children')->whereNull('parent_id')->get();
        return $this->transformCategories($categories);
    }

    private function transformCategories($categories)
    {
        return $categories->map(function ($category) {
            return [
                'id' => $category->id,
                'name' => $category->name,
                'children' => $this->transformCategories($category->children)
            ];
        });
    }

    public function updateCategory(Request $request, $id)
    {
        $category = Category::findOrFail($id);
        $category->update($request->all());

        Cache::forget('category_navigation');

        return response()->json(['message' => 'Category updated successfully']);
    }
}

In this example:

  1. We cache the entire category navigation tree for an hour.
  2. The buildNavigationTree method constructs a hierarchical structure of categories, which could be a costly operation on a large e-commerce site.
  3. When a category is updated, we invalidate the cache to ensure the navigation reflects the latest changes.

This approach can dramatically improve the performance of your e-commerce site. Instead of building the category tree on every request, which might involve multiple database queries and complex data manipulation, we do this once per hour. For a busy e-commerce site serving thousands of requests per minute, this can lead to significant performance improvements and reduced database load.

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe