Laravel 8 was released yesterday with a ton of new features and changes. One of those changes was the removal of the default route namespacing.
Although this change is backward-compatible, meaning that older projects that used Laravel 7.x can easily migrate to Laravel 8.x without having to change anything, new projects created in Laravel 8 (starting 8/Sep) have to take this into account.
Many developers have been facing an issue in their newly created Laravel 8 apps where they try to load their routes and they run into an Exception that says something like:
The issue is not that the code is broken, but that 99.9% of Laravel tutorials are now broken in this department because most of them relied on this default namespace for the string syntax.
Up until Laravel 7, the RouteServiceProvider.php file had the following code:
What this does is tell Laravel to load the routes in routes/web.php, using the web middleware and the App\Http\Controllers namespace. This, in turn, means that whenever you declared a route using the string-syntax, Laravel would look for that controller in the App\Http\Controllers folder:
In Laravel 8, the $namespace variable was removed and the Route declaration was changed to:
Now, Laravel is looking for routes inside your web.php file, as always. It’s also applying the web middleware, as always. But notice that it’s no longer using the previous namespace.
This means that starting in Laravel 8, when you declare your routes using the string-syntax, Laravel isn’t going to look for your controller inside App\Http\Controllers.
How do I fix this?
The problem here is that Laravel has no idea where to look for your controller, so all we have to do is let it know! There are 3 ways you can accomplish this:
- Add the namespace back manually so you can use it as you did in Laravel 7.x and before
- Use the full namespace in your route files when using the string-syntax
- Use the action syntax (recommended)
Adding the namespace manually
This is fairly simple. Go into your RoutesServiceProvider.php file and you’ll see the following:
All you need to do is add the following three lines to this file and Laravel will go back to using the default namespace as in Laravel 7.x:
What did we just do? We declared the $namespace variable with the default Namespace for our controllers and told laravel to use that for our web and api routes.
If you try to run your app again, everything should be working.
Using the full namespace
This one involves changing all your route declarations, but the idea is simple: prepend your controller names with their namespace. See the following example for our PostsController inside the app/Http/Controllers folder.
If you try again, everything should be running smoothly.
Using the Action Syntax
This is the alternative I personally recommend as I find it more typo-proof and in my experience provides better IDE support as we are explicitly telling the code which class to use. Instead of using our usual string syntax, we can use the action syntax where we specify the class and method to use in an array:
Notice here we are not passing the PostsController within quotes but rather PostsController::class, which internally will return ‘App\Http\Controllers\PostsController’. The second value in the array is the method to call within that controller, meaning: “In PostsController.php call the ‘all’ method.
Again, if you try to run your app again, everything should be up and running.
By now, your app should be up and running again. If not, please feel free to ask for help. Everyone in the community is eager to give a hand.
Whether you added the namespace manually, specified the full namespace in your routes, or went with the action syntax, what you just did is tell Laravel in which namespace your controllers actually are, so now it actually knows where to look.
If you liked what you read or want to learn more cool stuff related to Laravel, you can follow me on Twitter, where I post about coding, entrepreneurship, and living a better life.