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