How to use Laravel 7 style controller route definitions in Laravel 8

Amit Merchant · September 16, 2020 ·

One of the most prominent changes in Laravel 8 is the (kind of) new way of defining controller routes. Before Laravel 8, if you wanted to define a route, you could do it like so.

Route::get('/home', '[email protected]']);

Here, as you can tell, UserController is the controller and index in the method of the controller we want to call on this route.

Now, this was used to work fine because, under the hood, Laravel used to append controller namespace using the $namespace property of the app/Providers/RouteServiceProvider like so.

protected $namespace = 'App\Http\Controllers';

So, the previous route definition would get resolved to the following.

Route::get('/home', 'App\Http\Controllers\[email protected]']);

What’s changed in Laravel 8?

With the release of Laravel 8, the aforementioned way would not work. And if you do, you’ll get the following error.

Illuminate\Contracts\Container\BindingResolutionException
Target class [HomeController] does not exist.

This is because the $namespace property I talked about previously has been completely removed from app/Providers/RouteServiceProvider.

So, if you’ve just bootstrapped a new application using Laravel 8, you can start using the new syntax which encourages you to use Fully Qualified Class Names (FQCN) for controllers like so.

use App\Http\Controllers\HomeController;

Route::get('/home', [HomeController::class, 'index']);

Using old route definitions in Laravel 8

But if you’re like me who has just upgraded his/her Laravel application from 7.x to 8.x and still want to use the old syntax, you can add the $namespace property back to the app/Providers/RouteServiceProvider like so.

protected $namespace = 'App\Http\Controllers';

And apart from this, in the boot method of RouteServiceProvider, you’ll need to assign this namespace to the routes like so.

public function boot()
{
    $this->configureRateLimiting();

    $this->routes(function () {
        Route::middleware('web')
            ->namespace($this->namespace) // Assigning namespace
            ->group(base_path('routes/web.php'));

        Route::prefix('api')
            ->namespace($this->namespace) // Assigning namespace
            ->middleware('api')
            ->group(base_path('routes/api.php'));
    });
}

And after doing all these changes, everything should work fine!

In closing

In my opinion, the newer syntax is much nicer than the previous one as it encourages to use FQCNs and this can help navigate to controller classes if you’re using IDEs like PhpStorm. So, you should consider refactoring your code to using this syntax to make things more accessible.

But if you don’t want to do upgrade to the new syntax, fret not! I’ve already explained you the way. ;)

Hi there! I'm Amit. I write articles about all things web development. If you like what I write and want me to continue doing the same, I would like you buy me some coffees. I'd highly appreciate that. Cheers!