320

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.

How can I fix it?


Thanks to the answers, 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 answers.

Route::get('register', 'App\Http\Controllers\Api\RegisterController@register');
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nguyễn Việt Dũng
  • 3,211
  • 2
  • 5
  • 5

32 Answers32

587

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)
...
lagbox
  • 48,571
  • 8
  • 72
  • 83
  • 6
    This was really driving me crazy. The comment above the $namespace variable says: "If specified, this namespace is automatically applied to your controller routes." Well it is NOT. You have to add ->namespace('App\Http\Controllers') as you pointed out. They should really change the comment in the source code... – shock_gone_wild Sep 10 '20 at 13:35
  • @shock_gone_wild that comment and property were removed from the Provider about 25 minutes ago, so in the next patch version of `laravel/laravel` it will be gone – lagbox Sep 10 '20 at 19:56
  • 2
    Why was the modification changed ? For Performance improvement? – CodeGuru Sep 13 '20 at 07:18
  • the video version of this answer (5 minutes) https://youtu.be/MfE1tnMG6fE – Wibisono Indrawan Sep 16 '20 at 06:33
  • With the newest version, we can now simply un comment `// protected $namespace = 'App\\Http\\Controllers';` in `app/Providers/RouteServiceProvider.php` since `->namespace($this->namespace)` is used in the route declarations in the boot method , right? Or am I misunderstanding something? – Wesley Smith Sep 23 '20 at 23:54
  • 1
    @WesleySmith as of 8.0.2 of `laravel/laravel` that is there for you to uncomment and use if you would like – lagbox Sep 24 '20 at 00:08
  • Hi, it's late but I am struggling to resolve the "Target class [] doest not exist", I am developing a laravel package, I did all good but when I register my routes with the right namespace, it gives me the error "Target class [CORRECT_NAMESPACE/CONTROLLER] doest not exist", can enyone telle me a probable reason? thanks – EL OUFIR Hatim Dec 14 '20 at 15:21
  • 4
    @lagbox The world is a wonderful place because of stackoverflow and people like you... – DragonFire Mar 02 '21 at 03:21
  • Any reason why using `Route::get('/users', [UserController::class, 'index'])->name('users);` would still return this error? Ultimately I used your updated option and it worked, but I am curious to know what happened. – Andrew Fox Jun 11 '21 at 20:09
  • Uppdate 2021. Use the New way as shown in the above answer. Works well in Laravel 8. Use this Route::get('route', [App\Http\Controllers\SocialController::class, 'redirect']); Dont use this format Route::get('route','SocialController@redirect'); In Earlier versions we just had to do "ControllerName@functionname" But now we literally have to do [App\Http\Controllers] Hope this gets simplified in future. Taylor Otwell is working really hard and has made a revolutionary framework. Love Laravel. – Zasha Sep 24 '21 at 22:35
82
  • Yes, in Laravel 8 this error does occur.
  • After trying many solutions I got this 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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohit Tagadiya
  • 3,373
  • 1
  • 25
  • 25
24

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 isn't any 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Haron
  • 2,371
  • 20
  • 27
23

In Laravel 8 the default is to remove the namespace prefix, so you can set the old way in Laravel 7 like:

In RouteServiceProvider.php, add this variable:

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

And update the 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'));
    });
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jignesh Joisar
  • 13,720
  • 5
  • 57
  • 57
23

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 to: app\Providers\RouteServiceProvider.php path and remove the comment:

protected $namespace = 'App\\Http\\Controllers';
OMi Shah
  • 5,768
  • 3
  • 25
  • 34
Mobarak Hossen
  • 767
  • 5
  • 7
14

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

The error that I got.

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

Now my project is working.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hedayatullah Sarwary
  • 2,664
  • 3
  • 24
  • 38
10

Laravel 8 updated RouteServiceProvider and it affects routes with the string syntax. You can change it like in previous answers, but the recommended way is using action syntax, not using route with string syntax:

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

It should be changed to:

Route::get('register', [RegisterController::class, 'register']);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
8

If you are using Laravel 8, just copy and paste my code:

use App\Http\Controllers\UserController;

Route::get('/user', [UserController::class, 'index']);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tijani
  • 89
  • 2
8

For the solution, just uncomment line 29:

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

in the app\Providers\RouteServiceProvider.php file.

Just uncomment line 29

Blues Clues
  • 1,694
  • 3
  • 31
  • 72
Bruno Garcia
  • 111
  • 4
  • 1
    this one solved my issue laravel 8.22.1 .. none of the above highly rated worked. Thx – Alpy Jan 19 '21 at 13:14
  • Very nice, I'm glad I could help you. – Bruno Garcia Aug 05 '22 at 19:51
  • This line was not commented before, after comment this line issue resolved. Can you explain why we need to comment(in my case) or uncomment it. Laravel version is 9. – Billu Aug 13 '22 at 19:45
8

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.

Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
7

Also check your route web.php file if your RegisterController is properly in place..

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\RegisterController;


Route::get('/register',[RegisterController::class,'index'])->name('register');
Route::post('/register',[RegisterController::class,'store']);

Route::get('/', function () {
    return view('test.index');
});
user635568
  • 196
  • 5
  • 11
5

In the web.php (or api.php) in the routes folder, use/add that missing Controller class.

use App\Http\Controllers\<name of controller class>
KalebC4
  • 23
  • 6
TimeToCodeTheRoad
  • 7,032
  • 16
  • 57
  • 70
4

One important thing to make sure you do after each change on the routes is clearing the cache (using Laravel 9):

php artisan route:clear
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
phoenix
  • 1,629
  • 20
  • 11
3

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'));
    });
}
Ivan Fretes
  • 668
  • 7
  • 11
2

In Laravel 8 you can use it like this:

Route::group(['namespace'=>'App\Http\Controllers', 'prefix'=>'admin',
 'as'=>'admin.', 'middleware' => ['auth:sanctum', 'verified']], function()
{
    Route::resource('/dashboard', 'DashboardController')->only([
        'index'
    ]);
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hariom nagar
  • 370
  • 3
  • 5
  • This was helpful for a different reason, when you don't want to autowire all the 5 methods that Laravel creates with the `Route::apiResource`. – Danny G Feb 26 '23 at 14:11
2

Just uncomment the below line from RouteServiceProvider (if does not exists then add it):

protected $namespace = 'App\\Http\\Controllers';
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jatin Kaklotar
  • 445
  • 5
  • 17
1

On a freshly installed Laravel 8, in the App/Providers/RouteServices.php file:

 /*
 * 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 line

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

That should help you run Laravel the old-fashioned way.

In case you are upgrading from lower versions of Laravel to 8 then you might have to implicitly add line

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

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

Shahzad Barkati
  • 2,532
  • 6
  • 25
  • 33
stanley mbote
  • 956
  • 1
  • 7
  • 17
1

In my case, I had the same error, because I forgot to capitalize the first letter of controllers in the path.

So I changed

use App\Http\controllers\HomeController;

to this:

use App\Http\Controllers\HomeController;

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nsamba Isaac
  • 357
  • 4
  • 14
0

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

Route::group(['namespace' => 'App\Http\Controllers\Api'], function () {
    Route::resource('user', 'UserController');
    Route::resource('book', 'BookController');
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Saroj Shrestha
  • 2,696
  • 4
  • 21
  • 45
0

Ensure you're using the correct name of the file in your route.

For example:

If your controller file was named User.php, make that you're referencing it with User and not UserController.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

In Laravel 9, there isn't any need to add a namespace in RouteServiceProvider.

Instead of

Route::resource('tickets', 'TicketController');

use

Route::resource('tickets', TicketController::class);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ahmed Eid
  • 192
  • 1
  • 8
0

I tried everything, didn't work, until I tried this 2nd time restart server

php artisan cache:clear
php artisan optimize

php artisan route:list
ZW23
  • 65
  • 5
0

I faced the same error when running php artisan route:list. In my case I had deleted the recourse controller yet the route was still defined. I had to make sure the class in question was commented off in my routes/web.php.

orups
  • 59
  • 5
0
    "Target class [] does not exist."

for me it was because another developer in the team added the middleware method to the routes group and forgot to write its name

    ->middleware('')
0

Please add the line

use App\Http\Controllers\RegisterController;

in the Web.php file.

Anes
  • 35
  • 1
  • 9
-1

In Laravel 8 the way routes are specified has changed:

Route::resource('homes', HomeController::class)->names('home.index');
navid
  • 1,022
  • 9
  • 20
-1

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
-1

It happened to me when I was 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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Carlton
  • 5,533
  • 4
  • 54
  • 73
-1

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

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

This will auto-comment the variable on save.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
einbulinda
  • 67
  • 1
-1

For me, I had to change my route naming to the more recently supported format, as others have mentioned:

use App\Http\Controllers\UserController;

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

However, it continued to give me the same errors, until I ran this terminal command:

php artisan route:clear
KalebC4
  • 23
  • 6
-1

It is interesting to notice that since laravel v8, it is possible to use Route::controller(MyController::class)
https://laravel.com/docs/10.x/routing#route-group-controllers

In my case, I change previous laravel v7 coded

// CRUD Sample
Route::group(['prefix' => 'sample'], function ($router) {       // sample
    Route::get('/', 'SampleController@index');
    Route::get('/new', 'SampleController@create')->middleware('auth');
    Route::post('/store', 'SampleController@store')->middleware('auth');
    Route::group(['prefix' => '/edit'], function ($router) {            // sample/edit/{number}
        Route::get('/{number}', 'SampleController@edit')->middleware('auth');
        Route::get('/{number}/{migrate?}', 'SampleController@edit')->middleware('auth');
        Route::post('/', 'SampleController@store')->middleware('auth');
    });
});

to less verbose (v8 or more… v10 in my case) :

// CRUD Sample
Route::controller(SampleController::class)->prefix('sample')->group(function () {
    Route::get('/', 'index');
    Route::get('/new', 'create')->middleware('auth');
    Route::post('/store', 'store')->middleware('auth');
    Route::prefix('/edit')->middleware('auth')->group(function () {         // sample/edit/{number}
        Route::get('/{number}', 'edit');
        Route::get('/{number}/{migrate?}', 'edit');
        Route::post('/', 'store');
    });
});

then php artisan route:cache
then php artisan route:list
doesn't return anymore errors !-)

I don't understand why ->prefix doesn't works each time, for example :

// CRUD Licence
/* doesn't work
Route::controller(LicenceController::class)->middleware('auth')->prefix('licence')->group(function () {
    Route::get('/', 'index');
    Route::get('/new', 'new');
    Route::post('/new', 'insert');
});
*/
// works :
Route::controller(LicenceController::class, function () {
    Route::get('/licence', 'index')->middleware('auth');
    Route::get('/licence/new', 'new')->middleware('auth');
    Route::post('/licence/new', 'insert')->middleware('auth');
});
bcag2
  • 1,988
  • 1
  • 17
  • 31
-1

Also, maybe need group into \App\Http\Kernel::$middlewareGroups its work for me

Xakki
  • 172
  • 1
  • 7