Quick summary: I need to programmatically clear the routes cache (unless there is another way using the RouteServiceProvider?) but Artisan::call('route:cache');
is throwing an error.
I have routes that are bound to arrays of slugs we pull out of our database. This is all working great except that on our CMS side, if we add a new entry the app gives us a 404 on that new URL because the routes are all already cached. I can’t be ssh-ing in and running php artisan route:cache
every time someone makes an edit.
I’ve tried to add an observer to the relevant model that runs route:cache
whenever there is a change to a slug or a new entry is added, but that’s throwing an exception. I can’t replicate it in my local setup because my routes aren’t cached locally!
Here are some snippets of what’s going on:
My RouteServiceProvider is set up like below (to serve the routes {location}
). Is there something I could be doing differently here?
// this does not seem to update the routes every time the app boots public function boot() { $locations = implode('|', Location::get()->pluck('slug')->toArray()); Route::pattern('location', '(' . $locations . ')'); parent::boot(); }
So, to reiterate, if I add a new Location
or modify an existing one, I get a 404 until having run php artisan route:cache
. But, I don’t want to have to clear the route cache manually, so I set up an observer like this:
use IlluminateSupportFacadesArtisan; use myAppModelsAppLocation; // this model observer is hardly a glowing example of DRY credo class LocationObserver { public function created(Location $location) { Artisan::call('route:cache'); } public function updated(Location $location) { if($location->isDirty('name')) { Artisan::call('route:cache'); } }
My app’s not really called ‘MyApp’, I’ve changed it here for privacy’s sake. Also, slug
changes whenever name
changes so I’m just checking for that.
But that gives an error. Here’s a screenshot from my logs:
Also interesting is that in php artisan tinker
I get a deprecated error when trying to run Artisan::call('route:cache')
which I’ve found a couple GitHub issues related to this but can’t work out how to solve it on my side.
Advertisement
Answer
First of all, I would use a diferent aproach where you simply have 1 route & 1 controller.
$router->get('location/{slug}', 'LocationController@show');
Then in your show method you can just try to fetch a Location from the database and return a 404 if none was found by that slug. That’s how I’d do it.
public function show(string $slug) { $location = Location::where('slug', '=', $slug)->first; if (!$location) { throw new LocationNotFoundException() } // rest of the code }
If you go your route, what your error is indicating is some filesystem
permission error.
Please verify the owner of the file bootstrap/cache/routes.php
with ls -la
and make sure that it is the same one as the user running your php process (ps aux | grep php
)