Astuces

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

Laravel “Target class [controller] does not exist”

Divulgation : en tant que partenaire Amazon, AliExpress, KDP, Alison, Hostinger, Printful... DiGiProUnic peut percevoir une commission sur les achats effectués via nos liens. Cela n’affecte jamais le prix que vous payez, ni nos recommandations.

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)

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

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

Bonus 2026 : le script qui corrige tout automatiquement

Récap ultra-rapide

(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.

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)

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.

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.

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é.

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

Partager cet article