Fix Laravel 11 Class App\Http\Controllers not found After Route Auto-Discovery
Laravel 11 encourages route auto-discovery and cleaner route files, but after upgrading or starting a new project you might see: Error: Class “App\Http\Controllers” not found Or: Target class [App\Http\Controllers\HomeController] does not exist. This often happens when mixing old routing style with the new auto-discovery approach, or when namespaces/folders don’t match what Laravel expects.
Let’s sort this out.
1. What route auto-discovery does in Laravel 11
By default, Laravel 11 loads routes from routes/web.php, routes/api.php, etc., and you usually write them like:
use App\Http\Controllers\HomeController;
use App\Http\Controllers\PostController;
Route::get('/', HomeController::class);
Route::get('/posts', [PostController::class, 'index']);
Laravel no longer adds App\Http\Controllers\ automatically to string-based routes. Also, new starter kits may use invokable controllers or single-action routes.
If you still have old-style strings like 'HomeController@index', you can hit the “Class App\Http\Controllers not found” error.
2. Don’t reference the namespace itself as a class
If you accidentally write this:
use App\Http\Controllers;
Route::get('/', [Controllers::class, 'HomeController@index']);
or:
Route::get('/', App\Http\Controllers);
you’ll get:
Class "App\Http\Controllers" not found
because App\Http\Controllers is a namespace, not a class.
Correct usage:
use App\Http\Controllers\HomeController;
Route::get('/', [HomeController::class, 'index']);
or for a single-action controller:
Route::get('/', HomeController::class);
3. Make sure controllers live in the right folder with correct namespace
Each controller should be in app/Http/Controllers (or a subfolder) with a matching namespace.
Example: app/Http/Controllers/HomeController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
public function __invoke()
{
return view('home');
}
}
If the file is in app/Http/Controllers/Front/HomeController.php, then:
namespace App\Http\Controllers\Front;
class HomeController extends Controller { ... }
and your route import:
use App\Http\Controllers\Front\HomeController;
If the namespace and folder don’t match, auto-loading will fail.
4. Use class-based imports in routes (no plain strings)
Avoid old string syntax in Laravel 11:
// Old – can cause "target class does not exist"
Route::get('/', 'HomeController@index');
Use:
use App\Http\Controllers\HomeController;
Route::get('/', [HomeController::class, 'index']);
When you rely on auto-discovery and typed controllers, this is the recommended style.
5. Clear caches and regenerate autoload
After moving controllers or changing namespaces, Laravel may still load old compiled routes and Composer maps.
From the project root:
composer dump-autoload
php artisan route:clear
php artisan config:clear
php artisan cache:clear
Then hit the route again.
6. Check RouteServiceProvider (if you customized it)
In Laravel 11, app/Providers/RouteServiceProvider.php usually looks like:
public function boot(): void
{
Route::middleware('web')
->group(base_path('routes/web.php'));
Route::prefix('api')
->middleware('api')
->group(base_path('routes/api.php'));
}
If you manually reintroduced an old $namespace property or changed the boot method to add ->namespace('App\Http\Controllers'), you might combine it with class imports and confuse things.
General rule:
- If you use fully qualified class names or
usestatements with::class, do not set a default namespace in RouteServiceProvider. - If you want to keep using string syntax, you can set the namespace, but that’s against current recommendations.
7. Example: clean Laravel 11 route with auto-discovery
app/Http/Controllers/DashboardController.php:
<?php
namespace App\Http\Controllers;
class DashboardController
{
public function index()
{
return view('dashboard');
}
}
routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\DashboardController;
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware(['auth'])
->name('dashboard');
No manual namespace, no string routes. This works well with Laravel 11’s default setup.
8. Quick checklist
When you see “Class App\Http\Controllers not found” or “Target class does not exist” in Laravel 11:
- Don’t use
App\Http\Controllersas a class; import specific controllers instead. - Ensure controller files live under
app/Http/Controllerswith correct namespaces. - Use
[Controller::class, 'method']orController::classfor invokable controllers, not'Controller@method'strings. - Clear route and config caches and run
composer dump-autoload. - Avoid adding custom namespaces in
RouteServiceProviderunless you know exactly why.
Once your namespaces, imports, and routes are aligned with Laravel 11’s style, route auto-discovery works smoothly and those “class not found errors” disappear.