Home > Enterprise >  Properly cache a type-hinted model in Laravel
Properly cache a type-hinted model in Laravel

Time:12-25

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.

CodePudding user response:

You can override the default model binding logic:

Models\Page.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

CodePudding user response:

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();
    }
    
}
  • Related