186
votes

Here is my controller:

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class RegisterController extends Controller
{
    public function register(Request $request)
    {
        dd('aa');
    }
}

As seen in the screenshot, the class exists and is in the correct place:

enter image description here

My api.php route:

Route::get('register', 'Api\RegisterController@register');

When I hit my register route using Postman, it gave me the following error:

Target class [Api\RegisterController] does not exist.


Update:

Thanks to the answer, I was able to fix it. I decided to use the fully qualified class name for this route, but there are other options as described in the answer.

Route::get('register', 'App\Http\Controllers\Api\RegisterController@register');
20
welcome to SO .. is your controller inside Api folder .?Kamlesh Paul
You need to regenerate the classes as composer dump-autoload or in your RegisterController is missing namespace.sta
@KamleshPaul yesNguyễn Việt Dũng
then try composer dump-autoloadKamlesh Paul

20 Answers

368
votes

You are using Laravel 8. In a fresh install of Laravel 8, there is no namespace prefix being applied to your route groups that your routes are loaded into.

"In previous releases of Laravel, the RouteServiceProvider contained a $namespace property. This property's value would automatically be prefixed onto controller route definitions and calls to the action helper / URL::action method. In Laravel 8.x, this property is null by default. This means that no automatic namespace prefixing will be done by Laravel." Laravel 8.x Docs - Release Notes

You would have to use the Fully Qualified Class Name for your Controllers when referring to them in your routes when not using the namespace prefixing.

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);
// or
Route::get('/users', 'App\Http\Controllers\UserController@index');

If you prefer the old way:

App\Providers\RouteServiceProvider:

public function boot()
{
    ...

    Route::prefix('api')
        ->middleware('api')
        ->namespace('App\Http\Controllers') // <---------
        ->group(base_path('routes/api.php'));

    ...
}

Do this for any route groups you want a declared namespace for.

The $namespace property:

Though there is a mention of a $namespace property to be set on your RouteServiceProvider in the Release notes and commented in your RouteServiceProvider this does not have any effect on your routes. It is currently only for adding a namespace prefix for generating URLs to actions. So you can set this variable, but it by itself won't add these namespace prefixes, you would still have to make sure you would be using this variable when adding the namespace to the route groups.

This information is now in the Upgrade Guide

Laravel 8.x Docs - Upgrade Guide - Routing

With what the Upgrade Guide is showing the important part is that you are defining a namespace on your routes groups. Setting the $namespace variable by itself only helps in generating URLs to actions.

Again, and I can't stress this enough, the important part is setting the namespace for the route groups, which they just happen to be doing by referencing the member variable $namespace directly in the example.

Update:

If you have installed a fresh copy of Laravel 8 since version 8.0.2 of laravel/laravel you can uncomment the protected $namespace member variable in the RouteServiceProvider to go back to the old way, as the route groups are setup to use this member variable for the namespace for the groups.

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

The only reason uncommenting that would add the namespace prefix to the Controllers assigned to the routes is because the route groups are setup to use this variable as the namespace:

...
->namespace($this->namespace)
...
45
votes
  • Yes, in laravel 8 this error does occur.
  • After trying many solutions I got these perfect solution.
  • Just follow the steps...

CASE - 1

We can change in api.php and in web.php files like below.
The current way we write syntax is

Route::get('login', 'LoginController@login');

That should be changed to:

Route::get('login', [LoginController::class, 'login']);

CASE - 2

  1. First go to the file: app > Providers > RouteServiceProvider.php
  2. In that file replace the line
    protected $namespace = null; with protected $namespace = 'App\Http\Controllers'; enter image description here
  3. Then add line ->namespace($this->namespace) as shown in image..
    enter image description here
16
votes

in laravel-8 default remove namespace prefix so you can set old way in laravel-7 like:

in RouteServiceProvider.php add this variable

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

and update boot method

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

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

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

In laravel 8 you just add your controller namespace in routes\web.php

use App\Http\Controllers\InvoiceController; // InvoiceController is controller name Route::get('invoice',[InvoiceController::class, 'index']);

Or

go `app\Providers\RouteServiceProvider.php` path and remove comments

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

9
votes

laravel 8 updated RouteServiceProvider and it affects route with string syntax, You can change it like above, but recommended way is using action syntax not using route with string syntax:

Route::get('register', 'Api\RegisterController@register');

Should be changed to:

Route::get('register', [RegisterController::class, 'register']);
5
votes

If you are using laravel 8

just copy and paste my code

use App\Http\Controllers\UserController;

Route::get('/user', [UserController::class, 'index']);
4
votes

The Laravel 8 documentation actually answers this issue more succinctly and clearly than any of the answers here:

Routing Namespace Updates

In previous releases of Laravel, the RouteServiceProvider contained a $namespace property. This property's value would automatically be prefixed onto controller route definitions and calls to the action helper / URL::action method. In Laravel 8.x, this property is null by default. This means that no automatic namespace prefixing will be done by Laravel. Therefore, in new Laravel 8.x applications, controller route definitions should be defined using standard PHP callable syntax:

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

Calls to the action related methods should use the same callable syntax:

action([UserController::class, 'index']);

return Redirect::action([UserController::class, 'index']);

If you prefer Laravel 7.x style controller route prefixing, you may simply add the $namespace property into your application's RouteServiceProvider.


There's no explanation as to why Taylor Otwell added this maddening gotcha, but I presume he had his reasons.

2
votes

In laravel-8 you can use like this

 Route::group(['namespace'=>'App\Http\Controllers', 'prefix'=>'admin',
 'as'=>'admin.','middleware'=>['auth:sanctum', 'verified']], function()
{
    Route::resource('/dashboard', 'DashboardController')->only([
        'index'
    ]);
});

Thanks

2
votes

If you would like to continue using the original auto-prefixed controller routing, you can simply set the value of the $namespace property within your RouteServiceProvider and update the route registrations within the boot method to use the $namespace property:

class RouteServiceProvider extends ServiceProvider
{
    /**
     * This namespace is applied to your controller routes.
     *
     * In addition, it is set as the URL generator's root namespace.
     *
     * @var string
     */
    protected $namespace = 'App\Http\Controllers';

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        $this->configureRateLimiting();

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

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

For solution just uncomment line 29:

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

in 'app\Providers\RouteServiceProvider.php' file.

just uncomment line 29

2
votes

I got the same error when I installed Laravel version 8.27.0: The error is as follow:

The Error that I got:

But when I saw my app/Providers/RouteServiceProvider.php I have namespaces inside my boot method, then I just uncommented this => protected $namespace = 'App\\Http\\Controllers';

Just Uncomment The protected $namespace = 'App\Http\Controllers';';

Now My Project is working:

Project is working safe and sound

I hope, this helps you.

1
votes

In case if you prefer grouping of this routes, you can do as :

Route::group(['namespace' => 'App\Http\Controllers\Api'], function () {
    Route::resource('user', 'UserController');
    Route::resource('book', 'BookController');
});

1
votes

On a freshly installed laravel 8, in the App/Providers/RouteServices.php

    * The path to the "home" route for your application.
 *
 * This is used by Laravel authentication to redirect users after login.
 *
 * @var string
 */
public const HOME = '/home';

/**
 * The controller namespace for the application.
 *
 * When present, controller route declarations will automatically be prefixed with this namespace.
 *
 * @var string|null
 */
// protected $namespace = 'App\\Http\\Controllers';

uncomment the

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

that should help you run laravel the old fashioned way.

Incase you are upgrading from lower versions of laravel to 8 then you might have to implicitly add the

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

in the RouteServices.php file for it to function the old way.

1
votes

In this issue, I just do add namespace like below and it works

enter image description here

1
votes

The way to define your routes in laravel 8 is either

// Using PHP callable syntax...
use App\Http\Controllers\HomeController;
Route::get('/', [HomeController::class, 'index']);

OR

// Using string syntax...
Route::get('/', 'App\Http\Controllers\HomeController@index');

A resource route becomes

// Using PHP callable syntax...
use App\Http\Controllers\HomeController;
Route::resource('/', HomeController::class);

This means that in laravel 8, there is no automatic controller declaration prefixing by default.

If you want to stick to the old way, then you need to add a namespace property in the app\Providers\RouteServiceProvider.php and activate in the routes method.

Follow this image instructions below:

enter image description here

1
votes

In the app/Providers folder, RouteServiceProvider.php change the protected $namespace; variable to

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

this will auto-comment the variable on save.

-1
votes

Just uncomment below line from RouteServiceProvider (If does not exists then add)

protected $namespace = 'App\\Http\\Controllers';
-1
votes

In Laravel 8 the way routes are specified has changed:

Route::resource('homes', HomeController::class)->names('home.index');
-1
votes

I had this error

(Illuminate\Contracts\Container\BindingResolutionException Target class [App\Http\Controllers\ControllerFileName] does not exist.

Solution: just check your class Name, it should be the exact same of your file name.

-1
votes

Happened to me when I passing null to the middleware function

Route::middleware(null)->group(function () {
    Route::get('/some-path', [SomeController::class, 'search']);
});

Passing [] for no middleware works or probably just remove the middleware call if not using middleware :D