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

# Migratiegids van oude naar nieuwe structuur

> Stap voor stap migreren van de oude appstructuur van Laravel 10 naar het Slim Application Skeleton van Laravel 11 en later.

## Inleiding

Deze gids beschrijft hoe je migreert van de oude applicatiestructuur van Laravel 10 en eerder (een structuur met `Kernel`-klassen en meerdere service providers) naar het Slim Application Skeleton van Laravel 11 en later.

<Warning>
  **De officiële documentatie raadt deze migratie niet aan.**

  * De oude structuur van Laravel 10 **blijft gewoon werken** in Laravel 11 en later. Tot en met de huidige versies, inclusief Laravel 13, zijn er geen plannen om de ondersteuning te beëindigen.
  * De migratie is **volledig optioneel**. Niet verplicht en niet aanbevolen.
  * Begrijp je de verschillen tussen de oude en nieuwe structuur niet grondig, dan raden we je sterk aan de migratie achterwege te laten. Dit is werk voor ontwikkelaars die de interne werking van het framework goed kennen.
  * **Maak vóór de migratie altijd een back-up** en controleer dat alle tests slagen.
</Warning>

## Wanneer migreren nodig kan zijn

In de volgende situaties kun je een migratie overwegen:

* Je wilt het project laten aansluiten op de nieuwste standaardstructuur, zodat nieuwe teamleden het makkelijk kunnen vergelijken met de officiële documentatie
* Je wilt consistentie bewaren met packages en starter kits die met Laravel 11 of later zijn gemaakt
* Je wilt configbestanden en klassen uit de oude structuur opruimen en de codebase eenvoudiger maken

## Vereisten

Deze gids gaat uit van de volgende situatie:

* **De Laravel-versie-upgrade is afgerond** (`laravel/framework ^11.0` of hoger)
* Alle bestaande tests slagen
* Je begrijpt de applicatiestructuur van Laravel 11 en later (zie [Applicatiestructuur van Laravel 11 en later](/nl/advanced/app-structure))

## Migratievoorbeeld

We laten zien hoe je een project dat is gemaakt met Laravel 10 + Breeze (Blade-stack) migreert naar de nieuwe structuur, terwijl Breeze intact blijft.

<Steps>
  <Step title="bootstrap/app.php vervangen">
    Het oude `bootstrap/app.php` maakte een `$app`-instantie aan en registreerde de kernels. Dit vervang je door
    de `Application::configure()`-keten.

    **Oud (Laravel 10):**

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

    $app = new Illuminate\Foundation\Application(
        $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
    );

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

    $app->singleton(
        Illuminate\Contracts\Console\Kernel::class,
        App\Console\Kernel::class
    );

    $app->singleton(
        Illuminate\Contracts\Debug\ExceptionHandler::class,
        App\Exceptions\Handler::class
    );

    return $app;
    ```

    **Nieuw (Laravel 11 en later):**

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

    use Illuminate\Foundation\Application;
    use Illuminate\Foundation\Configuration\Exceptions;
    use Illuminate\Foundation\Configuration\Middleware;

    return Application::configure(basePath: dirname(__DIR__))
        ->withRouting(
            web: __DIR__.'/../routes/web.php',
            commands: __DIR__.'/../routes/console.php',
            health: '/up',
        )
        ->withMiddleware(function (Middleware $middleware) {
            //
        })
        ->withExceptions(function (Exceptions $exceptions) {
            //
        })->create();
    ```

    <Info>
      De callbacks van `withMiddleware()` en `withExceptions()` zijn de plek waar je de configuratie van de kernelbestanden die je in de volgende stappen verwijdert naartoe verhuist. Laat ze eerst leeg; je vult ze aan in de volgende stappen.
    </Info>
  </Step>

  <Step title="De HTTP-kernel (app/Http/Kernel.php) verwijderen">
    In `app/Http/Kernel.php` stonden de globale middleware, middlewaregroepen en middleware-aliassen gedefinieerd.

    **Oud (app/Http/Kernel.php):**

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

    namespace App\Http;

    use Illuminate\Foundation\Http\Kernel as HttpKernel;

    class Kernel extends HttpKernel
    {
        protected $middleware = [
            \App\Http\Middleware\TrustProxies::class,
            \Illuminate\Http\Middleware\HandleCors::class,
            \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
            \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
            \App\Http\Middleware\TrimStrings::class,
            \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        ];

        protected $middlewareGroups = [
            'web' => [
                \App\Http\Middleware\EncryptCookies::class,
                \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
                \Illuminate\Session\Middleware\StartSession::class,
                \Illuminate\View\Middleware\ShareErrorsFromSession::class,
                \App\Http\Middleware\VerifyCsrfToken::class,
                \Illuminate\Routing\Middleware\SubstituteBindings::class,
            ],
            'api' => [
                \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
                \Illuminate\Routing\Middleware\SubstituteBindings::class,
            ],
        ];

        protected $middlewareAliases = [
            'auth' => \App\Http\Middleware\Authenticate::class,
            // ...
        ];
    }
    ```

    In Laravel 11 zit bovenstaande middleware als standaardwaarden ingebouwd in het framework. Heb je **geen** aanpassingen, dan kun je `app/Http/Kernel.php`
    direct verwijderen.

    **Heb je wel aanpassingen** (eigen middleware toegevoegd of uitgesloten), verhuis die dan eerst naar `withMiddleware()`
    in `bootstrap/app.php` en verwijder het bestand daarna.

    ```php theme={null}
    ->withMiddleware(function (Middleware $middleware) {
        // Globale middleware toevoegen
        $middleware->append(\App\Http\Middleware\MyCustomMiddleware::class);

        // Middleware toevoegen aan de web-groep
        $middleware->web(append: [
            \App\Http\Middleware\HandleInertiaRequests::class,
        ]);

        // Middleware-aliassen toevoegen
        $middleware->alias([
            'role' => \App\Http\Middleware\CheckRole::class,
        ]);
    })
    ```

    Zodra de verhuizing klaar is, verwijder je `app/Http/Kernel.php`.

    <Info>
      In Laravel 11 kun je ook de standaard-middlewareklassen zoals `TrustProxies`, `EncryptCookies` en `VerifyCsrfToken`
      verwijderen uit `app/Http/Middleware/`. Ze zitten ingebouwd in het framework, dus zonder aanpassingen heb je de bestanden zelf niet meer nodig.
    </Info>
  </Step>

  <Step title="De consolekernel (app/Console/Kernel.php) verwijderen">
    `app/Console/Kernel.php` verzorgde de scheduledefinities en het automatisch laden van commands.

    **Oud (app/Console/Kernel.php):**

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

    namespace App\Console;

    use Illuminate\Console\Scheduling\Schedule;
    use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

    class Kernel extends ConsoleKernel
    {
        protected function schedule(Schedule $schedule): void
        {
            // $schedule->command('inspire')->hourly();
        }

        protected function commands(): void
        {
            $this->load(__DIR__.'/Commands');
            require base_path('routes/console.php');
        }
    }
    ```

    **Het automatisch laden van commands** is in Laravel 11 en later overbodig geworden: de map `app/Console/Commands/` wordt automatisch gescand, dus de regel met `$this->load()`
    is niet meer nodig.

    **De scheduledefinities** verhuis je naar `routes/console.php` of naar `withSchedule()` in `bootstrap/app.php`.

    ```php theme={null}
    // routes/console.php (Laravel 11 en later)
    use Illuminate\Support\Facades\Schedule;

    Schedule::command('emails:send')->daily();
    ```

    Verwijder daarna `app/Console/Kernel.php`.

    <Info>
      Verwijder de bestanden van je eigen Artisan-commands in de map `app/Console/` niet. Laat de commandbestanden staan en verwijder alleen het bestand van de kernelklasse.
    </Info>
  </Step>

  <Step title="De exception handler (app/Exceptions/Handler.php) verwijderen">
    `app/Exceptions/Handler.php` verzorgde de configuratie van exceptierapportage en -rendering.

    **Oud (app/Exceptions/Handler.php):**

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

    namespace App\Exceptions;

    use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
    use Throwable;

    class Handler extends ExceptionHandler
    {
        protected $dontFlash = [
            'current_password',
            'password',
            'password_confirmation',
        ];

        public function register(): void
        {
            $this->reportable(function (Throwable $e) {
                //
            });
        }
    }
    ```

    Heb je aanpassingen, verhuis die dan eerst naar `withExceptions()` in `bootstrap/app.php` en verwijder het bestand daarna.

    ```php theme={null}
    use Throwable;
    use Illuminate\Http\Request;

    ->withExceptions(function (Exceptions $exceptions) {
        // Exceptierapportage aanpassen
        $exceptions->report(function (Throwable $e) {
            // ...
        });

        // Exceptierendering aanpassen
        $exceptions->render(function (\App\Exceptions\InvalidOrderException $e, Request $request) {
            return response()->view('errors.invalid-order', status: 500);
        });
    })
    ```

    Had je eigen items toegevoegd aan `$dontFlash`, dan verhuis je die op dezelfde manier.

    ```php theme={null}
    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->dontFlash([
            'my_sensitive_field',
        ]);
    })
    ```

    Zodra de verhuizing klaar is, verwijder je `app/Exceptions/Handler.php`.
  </Step>

  <Step title="De RouteServiceProvider verwijderen en routeregistratie verhuizen">
    `app/Providers/RouteServiceProvider.php` verzorgde het laden van routebestanden en de configuratie van rate limiting.

    **Oud (app/Providers/RouteServiceProvider.php):**

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

    namespace App\Providers;

    use Illuminate\Cache\RateLimiting\Limit;
    use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\RateLimiter;
    use Illuminate\Support\Facades\Route;

    class RouteServiceProvider extends ServiceProvider
    {
        public const HOME = '/home';

        public function boot(): void
        {
            RateLimiter::for('api', function (Request $request) {
                return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
            });

            $this->routes(function () {
                Route::middleware('api')
                    ->prefix('api')
                    ->group(base_path('routes/api.php'));

                Route::middleware('web')
                    ->group(base_path('routes/web.php'));
            });
        }
    }
    ```

    **De registratie van routebestanden** verhuis je naar `withRouting()` in `bootstrap/app.php`.

    ```php theme={null}
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php', // Als je API-routes gebruikt
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ```

    **Rate limiting** verhuis je naar `AppServiceProvider::boot()`.

    ```php theme={null}
    // app/Providers/AppServiceProvider.php
    use Illuminate\Cache\RateLimiting\Limit;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\RateLimiter;

    public function boot(): void
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });
    }
    ```

    Gebruik je ergens de constante `HOME`, vervang die dan door de URL-string zelf of verplaats de constante naar de `AppServiceProvider`.

    Verwijder daarna `app/Providers/RouteServiceProvider.php`.
  </Step>

  <Step title="Service providers opruimen">
    In Laravel 10 waren er standaard vijf service providers. Deze voeg je samen tot één bestand: `AppServiceProvider.php`.

    **Te verwijderen providers (eerst de inhoud verhuizen naar de AppServiceProvider, dan verwijderen):**

    | Bestand                                      | Nieuwe locatie                                                            |
    | -------------------------------------------- | ------------------------------------------------------------------------- |
    | `app/Providers/AuthServiceProvider.php`      | `Gate::policy()` e.d. in `AppServiceProvider::boot()`                     |
    | `app/Providers/BroadcastServiceProvider.php` | Bij gebruik van broadcasting: `withBroadcasting()` in `bootstrap/app.php` |
    | `app/Providers/EventServiceProvider.php`     | `Event::listen()` e.d. in `AppServiceProvider::boot()`                    |
    | `app/Providers/RouteServiceProvider.php`     | In de vorige stap al afgehandeld                                          |

    **Voorbeeld: de inhoud van het oude app/Providers/AuthServiceProvider.php verhuizen:**

    ```php theme={null}
    // Oud: app/Providers/AuthServiceProvider.php
    use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

    class AuthServiceProvider extends ServiceProvider
    {
        protected $policies = [
            Post::class => PostPolicy::class,
        ];

        public function boot(): void
        {
            $this->registerPolicies();
        }
    }
    ```

    ```php theme={null}
    // Nieuw: app/Providers/AppServiceProvider.php
    // Volg je de standaard naamgevingsconventies van Laravel, dan worden policies automatisch gedetecteerd en is dit niet nodig
    use Illuminate\Support\Facades\Gate;

    class AppServiceProvider extends ServiceProvider
    {
        public function boot(): void
        {
            Gate::policy(Post::class, PostPolicy::class);
        }
    }
    ```

    Zodra je de overbodige providerbestanden hebt verwijderd, verwijder je de `providers`-array uit `config/app.php`.

    ```php theme={null}
    // De providers-array in config/app.php
    // Je mag alles verwijderen
    'providers' => ServiceProvider::defaultProviders()->merge([
    App\Providers\AppServiceProvider::class,
    // Verwijder ook de entries van de verwijderde providers
    // App\Providers\AuthServiceProvider::class, // verwijderen
    // App\Providers\EventServiceProvider::class, // verwijderen
    // App\Providers\RouteServiceProvider::class, // verwijderen
    ])->toArray(),
    ```

    Maak vervolgens `bootstrap/providers.php` aan om aan te sluiten op de nieuwe structuur.

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

    // bootstrap/providers.php
    return [
        App\Providers\AppServiceProvider::class,
    ];
    ```

    <Info>
      Als `bootstrap/providers.php` bestaat, geeft Laravel dit bestand voorrang als lijst van providers.
    </Info>
  </Step>

  <Step title="De basiscontrollerklasse bijwerken">
    De `Controller`-basisklasse van Laravel 10 gebruikte de traits `AuthorizesRequests` en `ValidatesRequests`. De nieuwe basisklasse van Laravel
    11 is een simpele abstracte klasse zonder deze traits.

    **Oud (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;

    class Controller extends BaseController
    {
        use AuthorizesRequests, ValidatesRequests;
    }
    ```

    **Nieuw (Laravel 11 en later):**

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

    namespace App\Http\Controllers;

    abstract class Controller
    {
        //
    }
    ```

    De functionaliteit die de traits boden, vervang je als volgt:

    | Oude manier (via trait)                 | Nieuwe manier                                                                                                        |
    | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
    | `$this->validate($request, $rules)`     | `$request->validate($rules)`                                                                                         |
    | `$this->authorize('update', $post)`     | `Gate::authorize('update', $post)`                                                                                   |
    | `$this->authorizeResource(Post::class)` | In Laravel 11 is er geen eenvoudig alternatief, dus laat je `App\Http\Controllers\Controller` in de Laravel 10-opzet |

    Gebruiken bestaande controllers de trait-methodes, dan kun je kiezen: elke controller aanpassen, of de traits in de `Controller`-basisklasse
    laten staan. Het blijft ook werken als je niet alles in één keer verandert.

    <Warning>
      Roepen de door Breeze of Jetstream gegenereerde authenticatiecontrollers `$this->validate()` of `$this->authorize()`
      aan, controleer dan zeker de werking voordat je de basisklasse wijzigt.
    </Warning>
  </Step>

  <Step title="Overbodige configbestanden verwijderen">
    Bestanden die je niet hebt gewijzigd ten opzichte van de standaard, zoals `config/cors.php`, `config/hashing.php` en `config/view.php`, kun je verwijderen. Laat gewijzigde bestanden staan.
  </Step>

  <Step title="public/index.php bijwerken">
    Dit bestand is aangepast aan de nieuwe structuur, dus je herschrijft het volledig.

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

    use Illuminate\Foundation\Application;
    use Illuminate\Http\Request;

    define('LARAVEL_START', microtime(true));

    // Determine if the application is in maintenance mode...
    if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
    require $maintenance;
    }

    // Register the Composer autoloader...
    require __DIR__.'/../vendor/autoload.php';

    // Bootstrap Laravel and handle the request...
    /** @var Application $app */
    $app = require_once __DIR__.'/../bootstrap/app.php';

    $app->handleRequest(Request::capture());
    ```
  </Step>

  <Step title="artisan bijwerken">
    Het artisan-bestand herschrijf je op dezelfde manier volledig.

    ```php theme={null}
    #!/usr/bin/env php
    <?php

    use Illuminate\Foundation\Application;
    use Symfony\Component\Console\Input\ArgvInput;

    define('LARAVEL_START', microtime(true));

    // Register the Composer autoloader...
    require __DIR__.'/vendor/autoload.php';

    // Bootstrap Laravel and handle the command...
    /** @var Application $app */
    $app = require_once __DIR__.'/bootstrap/app.php';

    $status = $app->handleCommand(new ArgvInput);

    exit($status);
    ```
  </Step>

  <Step title="tests/TestCase.php bijwerken">
    De trait `CreatesApplication` is niet meer nodig, dus je past dit aan.
    `tests/CreatesApplication.php` mag je verwijderen.

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

    namespace Tests;

    use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

    abstract class TestCase extends BaseTestCase
    {
        //
    }
    ```
  </Step>

  <Step title=".env, .env.example en phpunit.xml bijwerken">
    Er is het een en ander veranderd, zoals `CACHE_DRIVER` dat `CACHE_STORE` is geworden, en er zijn items bijgekomen; pas dit aan waar nodig.
    Deze wijzigingen raken ook configbestanden en de productieomgeving, dus wees hier voorzichtig mee.
    Je hoeft dit niet koste wat kost te volgen.
  </Step>

  <Step title="Werking controleren">
    Is de migratie afgerond, controleer dan de werking in deze volgorde:

    ```shell theme={null}
    # Configuratiecache legen
    php artisan config:clear
    php artisan route:clear
    php artisan cache:clear

    # Controleren of de routes correct zijn geregistreerd
    php artisan route:list

    # Tests uitvoeren
    php artisan test
    ```

    Treden er problemen op, herstel dan de verwijderde bestanden vanuit je back-up en bekijk de foutmeldingen.
  </Step>
</Steps>

## Bestandsstructuur na de migratie

Na de migratie ziet het project er als volgt uit (met de wijzigingen ten opzichte van de oude structuur):

```
app/
├── Console/
│   └── Commands/          ← eigen commands blijven staan
│   （Kernel.php is verwijderd）
├── Exceptions/
│   （Handler.php is verwijderd）
├── Http/
│   ├── Controllers/
│   │   └── Controller.php ← gewijzigd in een simpele abstracte klasse
│   └── Middleware/        ← eigen middleware blijft staan
│   （Kernel.php is verwijderd）
├── Models/
└── Providers/
    └── AppServiceProvider.php ← samengevoegd tot één bestand
    （AuthServiceProvider.php is verwijderd）
    （BroadcastServiceProvider.php is verwijderd）
    （EventServiceProvider.php is verwijderd）
    （RouteServiceProvider.php is verwijderd）
bootstrap/
├── app.php                ← vervangen door de Application::configure()-vorm
└── providers.php          ← nieuw aangemaakt
routes/
├── web.php
├── api.php                ← alleen indien nodig
└── console.php            ← ook de scheduledefinities staan hier
```

## Samenvatting

| Onderdeel                   | Oude locatie                             | Nieuwe locatie                                                       |
| --------------------------- | ---------------------------------------- | -------------------------------------------------------------------- |
| HTTP-middleware             | `app/Http/Kernel.php`                    | `withMiddleware()` in `bootstrap/app.php`                            |
| Exceptieafhandeling         | `app/Exceptions/Handler.php`             | `withExceptions()` in `bootstrap/app.php`                            |
| Scheduledefinities          | `app/Console/Kernel.php`                 | `routes/console.php`                                                 |
| Routeregistratie            | `app/Providers/RouteServiceProvider.php` | `withRouting()` in `bootstrap/app.php`                               |
| Lijst van service providers | `providers`-array in `config/app.php`    | `bootstrap/providers.php`                                            |
| Policyregistratie           | `app/Providers/AuthServiceProvider.php`  | Automatische registratie; handmatig via `AppServiceProvider::boot()` |
| Eventlisteners              | `app/Providers/EventServiceProvider.php` | Automatische registratie; handmatig via `AppServiceProvider::boot()` |

## Naslag

* [Applicatiestructuur van Laravel 11 en later](/nl/advanced/app-structure)
* [FAQ nieuwe appstructuur](/nl/advanced/app-structure-faq)
* [Officiële upgradegids (11.x)](https://github.com/laravel/docs/blob/11.x/upgrade.md)
* [Verschillen 10.x → 11.x in de laravel/laravel-repository](https://github.com/laravel/laravel/compare/10.x...11.x)
* [Controller.php in Laravel 10](https://github.com/laravel/laravel/blob/10.x/app/Http/Controllers/Controller.php)
* [Controller.php in Laravel 11](https://github.com/laravel/laravel/blob/11.x/app/Http/Controllers/Controller.php)


## Related topics

- [FAQ over de nieuwe appstructuur van Laravel 11+](/nl/advanced/app-structure-faq.md)
- [Migratiegids van laravel/ui naar Fortify](/nl/blog/ui-to-fortify.md)
- [Versiecompatibiliteit van packages beheren](/nl/advanced/package-versioning.md)
- [Upgradegids van Laravel 11 naar 12](/nl/blog/upgrade-11-to-12.md)
- [Applicatiestructuur van Laravel 11 en later](/nl/advanced/app-structure.md)
