skip to Main Content

I’m using Redis to cache different parts of my app. My goal is to not make a database query when the user is not logged in, as the app’s content don’t get updated regularly.

I cache the archive queries in my controller, however when I type hint a model in the controller, the model is retrieved from the database and then passed to the controller:

// My route
Route::get('page/{page:id}', [ PageController::class, 'show' ] );

// My controller
public function show ( Page $page ) {
    // Here, the $page will be the actual page model. 
    // It's already been queried from the database.
}

What I’m trying to do is to try and resolve the page from the cache first, and then if the cache does not contain this item, query the database. If I drop the Page type-hint, I get the desired result ( only the id is passed to controller ) but then I will lose the benefit of IoC, automatic ModelNotFoundException, and more.

I’ve come across ideas such as binding the page model to a callback and then parsing the request(), but seems like a bad idea.

Is there any way to properly achieve this? I noticed that Laravel eloquent does not have a fetching event, which would be perfect for this purpose.

2

Answers


  1. You can override the default model binding logic:

    ModelsPage.php

    public function resolveRouteBinding($value, $field = null)
    {
        return Cache::get(...) ?? $this->findOrFail($value);
    }
    

    Read more here https://laravel.com/docs/8.x/routing#customizing-the-resolution-logic

    Login or Signup to reply.
  2. In order to check for existence of the data in Redis, you shouldn’t type-hint the model into the controller’s action. Do it like this:

    public function show($pageId) {
    
        if(/* check if cached */) {
            // Read page from cache
        } else {
            Page::where('id', $pageId)->first();
        }
        
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search