Away Around For Caching Route Closures in Laravel

in case you haven’t heard/tried the cmnd “php artisan route:cache“, here it is from the docs

Using the route cache will drastically decrease the amount of time it takes to register all of your application’s routes. In some cases, your route registration may even be up to 100x faster

but slightly above that you will also read

Closure based routes cannot be cached. To use route caching, you must convert any Closure routes to controller classes.

and thats a big bummer, cuz even if you have a one closure based route, the cmnd will fail 😔.

so as i was working on my MenuPackage i wanted to find a way to send the params i get from the db to the page controller & sadly currently the only way to do so is to include those params into the url it self

Route::get('someurl/{param1}/{param2}/etc', 'action');

 

- therefore i thought about a couple of solution :

1- using Events

we Fire an event with the channel equal the route_name along with the data we want to pass

Event:fire('some_route_name',[$param1,$param2,$etc]);

then listen to it from within the action method, but as it turned out it wont work unless you first registered the listener which on the long run and with too many routes, this will prove to be bad.

2- using File

we Save everything to a file like

return [
  'some_route_name' => [
    'param1' => 'value',
    'param2' => 'value',
    'etc..' => 'value',
  ],

  // ...
];

then retrieve it by

array_get('the_file', 'some_route_name');

and yes that’s a very reasonable solution & i even use it at some part of the package, however i wanted to use something more subtle than that.

3- using Cache 💝

this doesn’t need any introduction, basically all you do is

Cache::forever('route_name', compact('param1', 'param2', 'etc..'));

and now ANYYYYYWHERE you want to retrieve those data you just use

extract(cache(Route::currentRouteName()));

 

# SO HOW DO WE CACHE A ROUTE CLOSURE ?

1- make a dummy controller

class DummyController extends Controller
{
    public function handle()
    {

    }
}

2- do all your logic somewhere then cache it, same as above.

3- change your closure based routes to use the new dummy controller

// before
Route::get('someurl', function(){
   // ...
});

// after
Route::get('some_url', 'DummyController@handle')->name('route_name');

4- inside that method we get the cached data then we do whatever we want with it

public function handle()
{
    $data = cache(Route::currentRouteName());

    return view($data['viewfile'])->with([
        'param1' => $data['param1'],
        'param2' => $data['param2'],
        'etc..' => $data['etc'],
    ]);
}

 

\\ ofcourse by now you may be thinking,
Why would you do all that rather than simply making a controller and have all your logic in there ?
well you don’t, you should always use controllers and you should NEVER include any logic in the route file,
however for those rare cases where using a closure makes more sense, you can use the above solution.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s