Laravel : “Target class [controller] does not exist”

Laravel “Target class [controller] does not exist”

(La solution complète qui marche en 2026 – même si tu es sur Laravel 8, 9, 10 ou 11)

Tu tapes php artisan route:list, tout est propre.
Tu cliques sur un lien ou tu lances un test… et là :

Target class [App\Http\Controllers\UserController] does not exist.

Ou pire, dans les logs :

Target class [UserController] does not exist.

Tu vérifies 10 fois : le fichier existe, le namespace est bon, tu as fait composer dump-autoload… rien n’y fait.
Je suis passé par là au moins 40 fois (projets perso, clients, migrations Laravel 8 → 11).
Voici la checklist définitive 2026, classée par fréquence réelle.

Les 8 causes les plus fréquentes (et comment les tuer en 30 secondes)

1. Laravel 8+ → tu utilises encore la syntaxe ancienne dans routes (80 % des cas)

Avant Laravel 8 :

Route::get('/users', 'UserController@index');

Depuis Laravel 8 (et obligatoire en 9+) :

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

Solution : remplace toutes les chaînes par [Controller::class, 'method']
Astuce 2026 : PHPStorm / VSCode + Laravel Idea te fait la conversion en 1 clic (Refactor → Convert String to Class)

2. Tu as oublié le use en haut du fichier routes/api.php ou routes/web.php

Très fréquent quand tu copies-colles une route.

// Mauvais
Route::get('/profile', [ProfileController::class, 'show']);

// Bon (si pas de use)
Route::get('/profile', [\App\Http\Controllers\ProfileController::class, 'show']);

Ou ajoute simplement en haut :

use App\Http\Controllers\ProfileController;

3. Le controller n’est pas dans le bon namespace

Laravel attend par défaut App\Http\Controllers

Si tu l’as mis ailleurs (ex: App\Http\Controllers\Admin\DashboardController) :

Route::get('/admin', [App\Http\Controllers\Admin\DashboardController::class, 'index']);

Ou crée un alias dans RouteServiceProvider.php (Laravel 9+) :

protected $namespace = 'App\Http\Controllers'; // déjà commenté par défaut

4. Cache de config/routes activé (très fréquent en prod)

Tu as modifié les routes, mais Laravel lit encore l’ancien cache.

Solution (30 sec) :

php artisan route:clear
php artisan config:clear
php artisan cache:clear
php artisan view:clear

Ou tout en une ligne :

php artisan optimize:clear

5. Tu es en Laravel 11 (nouvelle structure sans app/Http/Controllers par défaut)

Laravel 11 a changé la structure : les controllers sont dans app/Controllers ou directement à la racine app/.

Solution : déplace ton controller dans app/Controllers et ajuste le namespace :

namespace App\Controllers;

class UserController extends Controller { ... }

Et dans les routes :

use App\Controllers\UserController;

6. Tu utilises un préfixe ou un namespace dans RouteServiceProvider

Très fréquent sur les projets migrés de Laravel 7/8 vers 10/11.

Ouvre app/Providers/RouteServiceProvider.php :

// Si tu vois ça, c’est la source du mal :
protected $namespace = 'App\\Http\\Controllers';

// Supprime ou commente cette ligne (Laravel 9+ n’en a plus besoin)

Puis :

php artisan route:clear

7. Tu as un typo dans le nom de classe ou de méthode

  • UserContoller (un “l” en trop)
  • indxe au lieu de index

Solution rapide : lance cette commande magique (Laravel 9+) :

php artisan route:list --name=users

Elle te dira exactement quel controller/method Laravel cherche.

8. Composer n’a pas autoloadé ton nouveau controller

composer dump-autoload
# ou si tu es parano :
rm -rf bootstrap/cache/*
composer dump-autoload -o

Ma checklist “zéro prise de tête” que je colle dans tous mes projets Laravel 10/11

Dans routes/web.php et routes/api.php :

<?php

use App\Http\Controllers\ProfileController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\UserController;
// etc.

Route::middleware('auth')->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
    Route::resource('users', UserController::class);
});

Et je n’utilise jamais les strings.

Bonus 2026 : le script qui corrige tout automatiquement

Crée un fichier fix-routes.php à la racine :

<?php
require 'vendor/autoload.php';
$app = require_once 'bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();

use Illuminate\Support\Facades\Route;

Route::get('/fix-routes', function () {
    \Artisan::call('route:clear');
    \Artisan::call('config:clear');
    \Artisan::call('cache:clear');
    return "Routes & config vidés – tout devrait remarcher !";
});

Visite tonsite.com/fix-routes une fois → problème réglé.

Récap ultra-rapide

Tu as résolu le problème comment ?
Laravel 8 ? 10 ? 11 ? Dis-moi en commentaire ta version + ce qui a marché chez toi.
Ça aidera des centaines de devs qui tombent sur cet article à 3 h du matin en sueur.

Distribue-le à ton collègue qui t’envoie “ça marche en local mais pas en prod” pour la 5ᵉ fois cette semaine.

Tu veux comprendre l’étape suivante ? Node.js : “ERR_SSL_VERSION_OR_CIPHER_MISMATCH”

Tu peux aussi lire ceci pour mieux comprendre : Basic Routing

Laisser un commentaire