> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# FAQ sur la nouvelle structure d'application Laravel 11+

> Questions fréquentes et réponses sur la migration vers le Slim Application Skeleton de Laravel 11 et versions ultérieures. Destiné aux développeurs qui rejoignent en cours de route un projet mis à niveau en conservant l'ancienne structure, ou qui ont appris avec d'anciens livres ou tutoriels.

Avec Laravel 11, la structure d'application a été profondément modifiée sous le nom de « Slim Application Skeleton ». Cette page résume les points qui posent le plus souvent question, notamment lorsque vous rejoignez en cours de route un projet mis à niveau en conservant l'ancienne structure, ou si vous avez appris Laravel avec des livres ou tutoriels antérieurs à la version 10. Ce sont les questions les plus fréquemment posées sur les forums Laracasts et Stack Overflow à la sortie de Laravel 11.

<Info>
  Cette FAQ concerne les **nouveaux projets** (Laravel 11+). Pour la procédure de mise à niveau des projets existants, consultez le [guide de migration](/fr/advanced/app-structure-migration).
</Info>

<AccordionGroup>
  <Accordion title="Il y a peu de fichiers de configuration">
    Dans la nouvelle structure, les fichiers de configuration qui changent rarement ont été retirés du projet. Ce sont les fichiers `config/` du framework qui sont utilisés à leur place.

    Les fichiers `config/` du projet et ceux du framework sont fusionnés, **avec priorité au projet**. Il suffit de créer un fichier dans le projet au moment où vous souhaitez le personnaliser pour que les modifications soient prises en compte.

    ```bash theme={null}
    # Vérifier la configuration à l'intérieur du framework
    cat vendor/laravel/framework/config/cors.php

    # La copier dans le projet et la personnaliser
    php artisan config:publish cors
    ```
  </Accordion>

  <Accordion title="Impossible d'utiliser $this->validate() ou $this->authorize() dans les contrôleurs">
    Dans la nouvelle structure de Laravel 11, `App\Http\Controllers\Controller` est une classe vide qui n'hérite plus de `Illuminate\Routing\Controller` et n'utilise plus les traits `ValidatesRequests` / `AuthorizesRequests`.

    | Laravel 10                                | Laravel 11  |
    | ----------------------------------------- | ----------- |
    | Hérite de `Illuminate\Routing\Controller` | Classe vide |
    | Utilise le trait `ValidatesRequests`      | Aucun       |
    | Utilise le trait `AuthorizesRequests`     | Aucun       |

    Références : [Controller de Laravel 10](https://github.com/laravel/laravel/blob/10.x/app/Http/Controllers/Controller.php) vs [Controller de Laravel 11](https://github.com/laravel/laravel/blob/11.x/app/Http/Controllers/Controller.php)

    **Solutions de remplacement :**

    ```php theme={null}
    // Utiliser $request->validate()
    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
        ]);
    }

    // Utiliser Gate::authorize()
    use Illuminate\Support\Facades\Gate;

    public function update(Request $request, Post $post)
    {
        Gate::authorize('update', $post);
    }
    ```

    Si vous les utilisez fréquemment, vous pouvez également restaurer `App\Http\Controllers\Controller` comme dans Laravel 10.

    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
    use Illuminate\Foundation\Validation\ValidatesRequests;
    use Illuminate\Routing\Controller as BaseController;

    abstract class Controller extends BaseController
    {
        use AuthorizesRequests, ValidatesRequests;
    }
    ```
  </Accordion>

  <Accordion title="Il n'y a pas de app/Http/Middleware pour modifier la configuration des middlewares / il n'y a pas de app/Http/Kernel.php">
    Dans la nouvelle structure, `app/Http/Kernel.php` a été supprimé et la configuration des middlewares se fait via `withMiddleware()` dans `bootstrap/app.php`.

    ```php theme={null}
    // bootstrap/app.php
    ->withMiddleware(function (Middleware $middleware) {
        // Tous les paramètres qui se faisaient via TrustProxies et autres middlewares
        // peuvent maintenant être configurés via les méthodes de la classe Middleware
        $middleware->trustProxies(at: '*');

        // Ajouter un middleware global
        $middleware->append(\App\Http\Middleware\MyMiddleware::class);

        // Définir un alias pour les groupes de routes
        $middleware->alias([
            'my-middleware' => \App\Http\Middleware\MyMiddleware::class,
        ]);

        // Personnaliser les groupes de middlewares Web / API
        $middleware->web(append: [
            \App\Http\Middleware\HandleInertiaRequests::class,
        ]);
    })
    ```

    Les fichiers de middleware personnalisés continuent d'être créés dans `app/Http/Middleware/`.
  </Accordion>

  <Accordion title="Impossible d'utiliser $this->middleware() dans un contrôleur">
    `$this->middleware()` est une fonctionnalité de `Illuminate\Routing\Controller` et ne peut pas être utilisée avec le contrôleur de base vide de la nouvelle structure.

    À la place, implémentez l'interface `HasMiddleware` et définissez la méthode `middleware()`.

    ```php theme={null}
    use Illuminate\Routing\Controllers\HasMiddleware;
    use Illuminate\Routing\Controllers\Middleware;

    class UserController extends Controller implements HasMiddleware
    {
        public static function middleware(): array
        {
            return [
                'auth',
                new Middleware('log', only: ['index']),
                new Middleware('subscribed', except: ['index']),
            ];
        }
    }
    ```

    Depuis Laravel 13, l'attribut `#[Middleware]` est également utilisable.

    ```php theme={null}
    use Illuminate\Routing\Controllers\HasMiddleware;
    use App\Http\Middleware\EnsureTokenIsValid;

    #[Middleware(EnsureTokenIsValid::class)]
    class UserController extends Controller
    {
        // ...
    }
    ```

    Référence : [Middleware de contrôleur](https://laravel.com/docs/13.x/controllers#controller-middleware)
  </Accordion>

  <Accordion title="Il n'y a pas de $this->authorizeResource()">
    `authorizeResource()` dépend du trait `AuthorizesRequests` et ne peut donc pas être utilisée avec le contrôleur de base vide de la nouvelle structure.

    **Plusieurs approches sont possibles.**

    **1. Restaurer le contrôleur de base à la spécification Laravel 10 (le plus simple)**

    ```php theme={null}
    // app/Http/Controllers/Controller.php
    use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
    use Illuminate\Routing\Controller as BaseController;

    abstract class Controller extends BaseController
    {
        use AuthorizesRequests;
    }
    ```

    Cela rend `$this->authorizeResource()` à nouveau utilisable.

    **2. Appliquer l'attribut `#[Authorize]` de Laravel 13 à chaque méthode**

    ```php theme={null}
    use Illuminate\Routing\Attributes\Controllers\Authorize;
    use App\Models\Post;

    class PostController extends Controller
    {
        #[Authorize('view', 'post')]
        public function show(Post $post) { /* ... */ }

        #[Authorize('update', 'post')]
        public function update(Request $request, Post $post) { /* ... */ }
    }
    ```
  </Accordion>

  <Accordion title="Il n'y a pas de app/Console/Kernel.php pour configurer les tâches planifiées">
    Dans la nouvelle structure, `app/Console/Kernel.php` a été supprimé et l'emplacement de configuration des tâches planifiées a changé.

    **À écrire dans `routes/console.php` (recommandé) :**

    ```php theme={null}
    // routes/console.php
    use Illuminate\Support\Facades\Schedule;

    Schedule::command('emails:send')->daily();
    Schedule::job(new SendEmails)->everyFiveMinutes();
    ```

    **À écrire dans `bootstrap/app.php` :**

    ```php theme={null}
    ->withSchedule(function (Schedule $schedule) {
        $schedule->command('emails:send')->daily();
    })
    ```
  </Accordion>

  <Accordion title="Comment enregistrer les événements et les écouteurs ?">
    Dans la nouvelle structure, `EventServiceProvider` a été supprimé et il n'est plus nécessaire d'enregistrer manuellement les événements et les écouteurs.

    **Mécanisme d'enregistrement automatique :** en déclarant le type de la classe d'événement dans l'argument de la méthode `handle()` de la classe d'écouteur, l'enregistrement est effectué automatiquement.

    ```php theme={null}
    namespace App\Listeners;

    use App\Events\OrderShipped;

    class SendShipmentNotification
    {
        // Il suffit d'indiquer la classe d'événement comme argument de handle() pour qu'elle soit enregistrée automatiquement
        public function handle(OrderShipped $event): void
        {
            // ...
        }
    }
    ```

    Si un enregistrement manuel est nécessaire, faites-le dans `AppServiceProvider::boot()`.

    ```php theme={null}
    use Illuminate\Support\Facades\Event;

    public function boot(): void
    {
        Event::listen(
            OrderShipped::class,
            SendShipmentNotification::class,
        );
    }
    ```
  </Accordion>

  <Accordion title="Comment ajouter un service provider dans config/app.php ?">
    Dans la nouvelle structure, la gestion de la liste des service providers est passée de `config/app.php` à `bootstrap/providers.php`.

    ```php theme={null}
    // bootstrap/providers.php
    return [
        App\Providers\AppServiceProvider::class,
        App\Providers\MyCustomServiceProvider::class, // ← à ajouter ici
    ];
    ```

    Les providers créés avec `artisan make:provider` sont automatiquement ajoutés dans ce fichier.
  </Accordion>

  <Accordion title="Il n'y a pas de app/Exceptions/Handler.php">
    Dans la nouvelle structure, `app/Exceptions/Handler.php` a été supprimé et la configuration des exceptions se fait via `withExceptions()` dans `bootstrap/app.php`.

    ```php theme={null}
    // bootstrap/app.php
    ->withExceptions(function (Exceptions $exceptions) {
        // Ne pas reporter certaines exceptions
        $exceptions->dontReport(InvalidOrderException::class);

        // Rendu personnalisé
        $exceptions->render(function (InvalidOrderException $e, Request $request) {
            return response()->view('errors.invalid-order', status: 500);
        });

        // Changer la redirection en cas de non-authentification
        $exceptions->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
            return $request->is('api/*');
        });
    })
    ```
  </Accordion>

  <Accordion title="Comment personnaliser le routage ?">
    La personnalisation des routes se fait via `withRouting()` dans `bootstrap/app.php`.

    **Ajouter un fichier de routes :**

    ```php theme={null}
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        then: function () {
            Route::middleware('web')
                ->prefix('admin')
                ->group(base_path('routes/admin.php'));
        },
    )
    ```

    **Contrôle complet (équivalent au `RouteServiceProvider` de Laravel 10) :**

    En spécifiant `using`, l'enregistrement par défaut des routes de Laravel est totalement désactivé et vous contrôlez tout vous-même.

    ```php theme={null}
    ->withRouting(
        using: function () {
            Route::middleware('web')
                ->group(base_path('routes/web.php'));

            Route::middleware('api')
                ->prefix('api')
                ->group(base_path('routes/api.php'));
        },
    )
    ```
  </Accordion>

  <Accordion title="Comment remplacer un ServiceProvider par défaut de Laravel ?">
    En ajoutant une clé `providers` dans `config/app.php`, celle-ci est fusionnée avec le `config/app.php` du framework et prise en compte.

    ```php theme={null}
    // config/app.php
    use Illuminate\Support\ServiceProvider;

    return [
        // ...
        'providers' => ServiceProvider::defaultProviders()->replace([
            Illuminate\Foo\FooServiceProvider::class => Bar\BarServiceProvider::class,
        ])->toArray(),
    ];
    ```

    La méthode `replace()` permet de substituer un provider par défaut par votre propre implémentation.
  </Accordion>

  <Accordion title="Il n'y a pas de routes/api.php">
    Depuis Laravel 11, les fonctionnalités API ne sont pas incluses par défaut ; il faut les installer séparément lorsque vous en avez besoin.

    ```bash theme={null}
    php artisan install:api
    ```

    Cette commande crée et configure les éléments suivants :

    * `routes/api.php`
    * La configuration de [Laravel Sanctum](https://laravel.com/docs/sanctum) pour l'authentification API
    * L'enregistrement des routes API dans `bootstrap/app.php`
  </Accordion>

  <Accordion title="Il n'y a pas de routes/channels.php">
    Depuis Laravel 11, les fonctionnalités de broadcasting ne sont pas non plus incluses par défaut ; il faut les installer séparément lorsque vous en avez besoin.

    ```bash theme={null}
    php artisan install:broadcasting
    ```

    Cette commande crée et configure les éléments suivants :

    * `routes/channels.php`
    * L'installation de [Laravel Reverb](https://laravel.com/docs/reverb)
    * Les fichiers de configuration de broadcasting
  </Accordion>

  <Accordion title="Comment savoir si le projet que je rejoins utilise l'ancienne ou la nouvelle structure ?">
    Consultez le contenu de `bootstrap/app.php`.

    **Nouvelle structure Laravel 11+ (ou projet migré) :**

    ```php theme={null}
    // bootstrap/app.php
    return Application::configure(basePath: dirname(__DIR__))
        ->withRouting(...)
        ->withMiddleware(...)
        ->withExceptions(...)
        ->create();
    ```

    **Projet mis à niveau depuis Laravel 10 tout en gardant l'ancienne structure :**

    ```php theme={null}
    // bootstrap/app.php
    $app = new Illuminate\Foundation\Application(
        $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
    );

    $app->singleton(
        Illuminate\Contracts\Http\Kernel::class,
        App\Http\Kernel::class
    );
    // ...
    ```

    Si le format est `return Application::configure(...`, il s'agit de la nouvelle structure ; sinon, c'est un projet mis à niveau qui a conservé l'ancienne. Pour la procédure de migration d'un projet ancienne structure vers la nouvelle, consultez le [guide de migration](/fr/advanced/app-structure-migration).
  </Accordion>
</AccordionGroup>

## Pages associées

<Card title="Structure d'application Laravel 11+" icon="sitemap" href="/fr/advanced/app-structure">
  Vue d'ensemble de la nouvelle structure d'application et détail de l'implémentation interne de `ApplicationBuilder`.
</Card>

<Card title="Guide de migration de l'ancienne vers la nouvelle structure" icon="arrow-right" href="/fr/advanced/app-structure-migration">
  Procédure pour migrer d'une ancienne structure Laravel 10 vers la nouvelle structure Laravel 11+.
</Card>


## Related topics

- [Structure d'application Laravel 11+](/fr/advanced/app-structure.md)
- [Guide de migration de l'ancienne vers la nouvelle structure](/fr/advanced/app-structure-migration.md)
- [Structure des répertoires](/fr/directory-structure.md)
- [laravel/symfony-on-cloud — faire tourner une application Symfony sur Laravel Cloud](/fr/blog/symfony-on-cloud-introduction.md)
- [Laravel Folio](/fr/folio.md)
