Laravel: A Middleware to cache your Responses

Sometimes, it’s better to cache the whole thing in one part of your code rather than… welp, doing it everywhere.

Sometimes our applications do something so resource-taxing that it’s better to cache the result and return it. You’re totally fine with that approach, taking the result and caching it… until your Controller starts to pile up code in charge of cache management in multiple methods.

Why about just caching the Response?

Well, you can do that, with just a few lines.

Don’t repeat yourself, application!

Let’s start with having a problem to solve:

In my podcast application, the page shows statistics (duh!) about a particular Podcast, like its subscribers, average listen time, referrers, engagement, etc. The whole Request is very taxing, since it needs to call a class which generates all this by executing multiple statements in the Database.

Instead of just caching the whole Statistics controller methods, I will elegantly use a middleware for the whole Controller.

This makes the Statistics Controller more cleaner: methods are in charge of pushing the statistics, while the middleware caches the Response.

Creating a ResponseCacheMiddleware

This is easy, just fire up your favorite terminal and tell Artisan to create our new middleware:

php artisan make:middleware ResponseCacheMiddleware

This file will be located under , so after that we open it and start editing.

The Logic

The middleware logic is fairly simple: if the Request being made is already in the Cache, we will pull it from it and return it. When not, we will just let the Request hit the controller, save the result, and return it.

There are multiple ways to identify the Request, but just to be sure, we will combine the authenticated User ID along with the Request URL, allowing to cache the Response for each User authenticated, for 5 minutes. Or you can go the overkill way and use MD5.

The Cache Facade has a handy method called . This methods returns the Cache contents if it exists, otherwise it will execute the Closure, save it into the Cache, and return the result.

public function ($request, Closure $next)
{
$key = 'request|'.$request->url().'|'.$request->user->getId();
return Cache::remember($key, 300, function ($request, $next) {
return $next($request);
}
}

Okay, let’s recap. What the last line does is very simple: when the we hit the cache, it will return the Response. This response is made by using the , which is a Closure, and the data itself.

If you’re using PHP 7.4 or latest, short arrow functions are your friend:

return Cache::remember($key, 300, fn() => $next($request));

Since the first Request won’t be cached, the method will execute the closure, which will hit our Controller method. Once done, it will save it in the Cache by the , while it returns it to the middleware.

And that’s pretty much it. This will allow the Request to be cached.No need to install packages or add a cache into each Controller method. You can also add this as an alias into your middleware array, and add middleware parameters for convenience, and also only use the middleware on Requests.

The problem with caching the whole thing? It’s the whole thing!

Okay, not everything is pretty. As you noticed, caching the Response will inevitably also cache the whole thing, like the headers and the content itself. In other words, if you depend on dynamic parts of the Request, the cached response will return old data.

For example, a User changed its username after seeing a Podcast statistics. Next time it goes into the statistics, it will display the old username in the top of the page.

If that’s a problem for you, then you may want to cache other parts of your Response, like the views composers, or leverage your taxing logic to a separate Service which could use your application Cache itself. Of course, using this for an API response is totally cool and fine from some SPA requests.

If you want more power, there are is a nice post in Laravel News with some HTTP Cache packages you can use.

Graphic Designer graduate. Full Stack Web Developer. Retired Tech & Gaming Editor.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store