How to avoid all database calls using Spatie Response Cache package

2 min read

It's no secret I stan Spatie packages. I'm convinced there must be something in the water over there in Belgium, because, all they seem to do is pump out quality package after quality package. And, the most impressive thing is that they're all incredibly well maintained.

Fanboy-ing aside, I noticed a gotcha when using the Response Cache package, specifically some custom route binding rules:

// RouteServiceProvider.php

        Route::bind('post', function($value) {
            return Post::where('slug', $value)->firstOrFail();

What the code above allows me to do is bind routes via the slug column in my database. so /posts/my-awesome-post would map to a post with my-awesome-post as the slug.

The problem

This is all well and good, however, despite caching this route, we will still incur a database call. This is because the route binding expressed above is run before Spatie's cache middleware.

The workaround

The workaround for this is fetching the record from the controller action. This will allow the response to be truly cached.

// PostsController.php 

public function show(string $slug)
    return Post::where('slug', $value)->firstOrFail();

While we lose the spiffy custom route model binding above, we prevent a database hit for each request.

This solution isn't perfect, and I'm open to other ways of doing it, but I wanted to put this out there should anyone else encounter the same quirk.

Happy coding!