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

# Applicatiestructuur van Laravel 11 en later

> Een compleet overzicht van het in Laravel 11 geïntroduceerde Slim Application Skeleton en de interne implementatie van Application::configure() tot en met de ApplicationBuilder.

## Vergelijking met Laravel 10 en eerder

In Laravel 11 is de applicatiestructuur grondig vernieuwd onder de naam "Slim Application Skeleton". De grootste verandering is dat de verspreide configuratie is samengebracht op één plek: `bootstrap/app.php`.

| Onderdeel         | Laravel 10 en eerder                           | Laravel 11 en later                              |
| ----------------- | ---------------------------------------------- | ------------------------------------------------ |
| HTTP-kernel       | `app/Http/Kernel.php`                          | Vervallen (opgenomen in het framework)           |
| Consolekernel     | `app/Console/Kernel.php`                       | Vervallen (verhuisd naar `routes/console.php`)   |
| Exception handler | `app/Exceptions/Handler.php`                   | Vervallen (samengebracht in `bootstrap/app.php`) |
| Service providers | 5 bestanden                                    | 1 bestand: `AppServiceProvider.php`              |
| Routebestanden    | `web.php` / `api.php` standaard                | Alleen `web.php` standaard, `api.php` is opt-in  |
| Bootstrap         | Configuratie verspreid over meerdere bestanden | Samengebracht in `bootstrap/app.php`             |
| Standaarddatabase | MySQL/PostgreSQL                               | SQLite                                           |

<Info>
  Deze verandering geldt **voor nieuwe projecten**. Upgrade je een bestaande Laravel 10-applicatie, dan blijft de oude structuur gewoon werken.
</Info>

## De nieuwe mappen- en bestandsstructuur

### Mappenstructuur van het skeleton

```
laravel-app/
├── app/
│   ├── Http/
│   │   └── Controllers/
│   ├── Models/
│   │   └── User.php
│   └── Providers/
│       └── AppServiceProvider.php
├── bootstrap/
│   ├── app.php          ← het middelpunt van de applicatieconfiguratie
│   ├── cache/
│   └── providers.php    ← lijst van service providers
├── config/
├── database/
├── public/
│   └── index.php        ← entrypoint
├── resources/
├── routes/
│   ├── web.php          ← webroutes (standaard)
│   └── console.php      ← Artisan-commands en schedule
├── storage/
└── tests/
```

### `bootstrap/app.php` — het middelpunt van de appconfiguratie

```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): void {
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
```

Met dit ene bestand configureer je routing, middleware en exceptieafhandeling. In Laravel 10 en eerder was deze configuratie verspreid over drie bestanden — `app/Http/Kernel.php`, `app/Console/Kernel.php` en `app/Exceptions/Handler.php` — die hier nu zijn samengebracht.

### `bootstrap/providers.php` — lijst van service providers

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

use App\Providers\AppServiceProvider;

return [
    AppServiceProvider::class,
];
```

Dit bestand is de plek waar service providers worden geregistreerd. In Laravel 10 zette je die in de `providers`-array van `config/app.php`, maar dat is nu afgesplitst naar `bootstrap/providers.php`. Standaard bevat Laravel 11 alleen de `AppServiceProvider`.

<Tip>
  Installeer je een package met `composer require`, dan kan die package `bootstrap/providers.php` automatisch bijwerken. `config/app.php` wordt niet genegeerd, maar voor nieuwe registraties is `bootstrap/providers.php` de aanbevolen plek geworden.
</Tip>

### Wijzigingen in de map `routes/`

```
routes/
├── web.php      ← webroutes (worden standaard geladen)
└── console.php  ← definieert Artisan-commands en de schedule
```

`api.php` en `channels.php` bestaan standaard niet. Je genereert ze zo nodig met een Artisan-commando.

```shell theme={null}
# API-routes toevoegen (installeert api.php + Sanctum)
php artisan install:api

# Broadcasting toevoegen (installeert channels.php + Reverb e.d.)
php artisan install:broadcasting
```

In `routes/console.php` kun je ook de schedule definiëren.

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

use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;

Artisan::command('inspire', function () {
    $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');

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

### Vervallen bestanden

<AccordionGroup>
  <Accordion title="app/Http/Kernel.php vervallen">
    De HTTP-kernel is opgenomen in `Illuminate\Foundation\Http\Kernel` binnen het framework. Middleware pas je aan via `withMiddleware()` in `bootstrap/app.php`.

    ```php theme={null}
    // Laravel 10 en eerder: app/Http/Kernel.php
    protected $middleware = [
        \Illuminate\Http\Middleware\TrustProxies::class,
        // ...
    ];

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            // ...
        ],
    ];
    ```

    ```php theme={null}
    // Laravel 11 en later: bootstrap/app.php
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->web(append: [
            EnsureUserIsSubscribed::class,
        ]);

        $middleware->validateCsrfTokens(except: ['stripe/*']);
    })
    ```
  </Accordion>

  <Accordion title="app/Console/Kernel.php vervallen">
    De twee taken van de consolekernel zijn gescheiden. Artisan-commands plaats je in `app/Console/Commands/`, waar ze automatisch worden gedetecteerd, en de schedule schrijf je in `routes/console.php`.

    ```php theme={null}
    // Laravel 10 en eerder: app/Console/Kernel.php
    protected function schedule(Schedule $schedule): void
    {
        $schedule->command('emails:send')->daily();
    }
    ```

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

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

  <Accordion title="app/Exceptions/Handler.php vervallen">
    De exception handler is opgenomen in `Illuminate\Foundation\Exceptions\Handler` binnen het framework. Aanpassingen doe je via `withExceptions()` in `bootstrap/app.php`.

    ```php theme={null}
    // Laravel 10 en eerder: app/Exceptions/Handler.php
    public function register(): void
    {
        $this->reportable(function (InvalidOrderException $e) {
            // ...
        });
    }
    ```

    ```php theme={null}
    // Laravel 11 en later: bootstrap/app.php
    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->report(function (InvalidOrderException $e) {
            // ...
        });
    })
    ```
  </Accordion>
</AccordionGroup>

## Hoe `Application::configure()` werkt

### Implementatie binnen het framework

`Application::configure()` is een statische methode van `Illuminate\Foundation\Application`.

```php theme={null}
// Uit Illuminate\Foundation\Application
public static function configure(?string $basePath = null)
{
    $basePath = match (true) {
        is_string($basePath) => $basePath,
        default => static::inferBasePath(),
    };

    return (new Configuration\ApplicationBuilder(new static($basePath)))
        ->withKernels()
        ->withEvents()
        ->withCommands()
        ->withProviders();
}
```

Deze methode doet het volgende:

1. Bepaalt de rootmap van de applicatie op basis van `basePath`
2. Maakt een `Application`-instantie aan
3. Wikkelt die in een `ApplicationBuilder` en past de standaardconfiguratie toe
4. Geeft de `ApplicationBuilder`-instantie terug

Belangrijk is dat binnen `configure()` **`withKernels()` / `withEvents()` / `withCommands()` / `withProviders()` al worden aangeroepen**. Je hoeft deze in `bootstrap/app.php` niet opnieuw aan te roepen.

### Configureren via method chaining

```php theme={null}
Application::configure(basePath: dirname(__DIR__))  // geeft een ApplicationBuilder terug
    ->withRouting(...)       // configureert routing en geeft $this terug
    ->withMiddleware(...)    // configureert middleware en geeft $this terug
    ->withExceptions(...)    // configureert exceptieafhandeling en geeft $this terug
    ->create();              // geeft een Application-instantie terug
```

De aanroep van `create()` haalt de `Application`-instantie uit de `ApplicationBuilder`; wat `bootstrap/app.php` uiteindelijk met `return` teruggeeft, is deze `Application`-instantie.

## Van request tot opgestarte app

```mermaid theme={null}
flowchart TD
    A["public/index.php<br>entrypoint"] --> B["bootstrap/app.php<br>requiren en de Application ophalen"]
    B --> C["Application::configure()<br>ApplicationBuilder aanmaken"]
    C --> D["withKernels()<br>HTTP-/consolekernel registreren"]
    D --> E["withEvents()<br>event discovery configureren"]
    E --> F["withCommands()<br>paden van Artisan-commands configureren"]
    F --> G["withProviders()<br>bootstrap/providers.php inladen"]
    G --> H["withRouting()<br>routing configureren"]
    H --> I["withMiddleware()<br>middleware configureren"]
    I --> J["withExceptions()<br>exceptieafhandeling configureren"]
    J --> K["create()<br>Application-instantie teruggeven"]
    K --> L["HTTP-kernel verwerkt het request<br>middleware → router → controller"]
    L --> M["response teruggeven"]
```

`public/index.php` is het entrypoint: het laadt `bootstrap/app.php` en verkrijgt zo de `Application`. Daarna stuurt de HTTP-kernel het request door de middleware-pipeline en dispatcht de router het naar de controller.

## Verdieping: de belangrijkste methodes van de `ApplicationBuilder`

### `withRouting()` — de interne verwerking van routeregistratie

```php theme={null}
public function withRouting(
    ?Closure $using = null,
    array|string|null $web = null,
    array|string|null $api = null,
    ?string $commands = null,
    ?string $channels = null,
    ?string $pages = null,
    ?string $health = null,
    string $apiPrefix = 'api',
    ?callable $then = null
)
```

Intern registreert dit een callback via `AppRouteServiceProvider::loadRoutesUsing()` en wordt de `AppRouteServiceProvider` geregistreerd tijdens het booten van de applicatie.

```php theme={null}
// De interne verwerking van withRouting() (vereenvoudigd)
protected function buildRoutingCallback(...)
{
    return function () use ($web, $api, $pages, $health, $apiPrefix, $then) {
        if (is_string($api) || is_array($api)) {
            Route::middleware('api')->prefix($apiPrefix)->group($api);
        }

        if (is_string($health)) {
            Route::get($health, function () {
                Event::dispatch(new DiagnosingHealth);
                return response(View::file(...), status: 200);
            });
        }

        if (is_string($web) || is_array($web)) {
            Route::middleware('web')->group($web);
        }

        if (is_callable($then)) {
            $then($this->app);
        }
    };
}
```

**Aandachtspunten:**

* Op `api`-routes worden automatisch de `api`-middlewaregroep en de `/api`-prefix toegepast
* Geef je een string door aan `health`, dan wordt automatisch een healthcheck-endpoint geregistreerd (standaard `/up`)
* Het pad van `health` wordt ook tijdens onderhoudsmodus uitgezonderd (ingesteld via `PreventRequestsDuringMaintenance::except()`)
* Let op: `api` wordt vóór `web` geregistreerd. Definieer je op hetzelfde pad zowel een web- als een API-route, dan krijgt de API-route voorrang
* Geef je een string door aan `pages`, dan wordt de routing van [Laravel Folio](https://github.com/laravel/folio) ingeschakeld

### `withMiddleware()` — middleware aanpassen

```php theme={null}
public function withMiddleware(?callable $callback = null)
{
    $this->app->afterResolving(HttpKernel::class, function ($kernel) use ($callback) {
        $middleware = (new Middleware)
            ->redirectGuestsTo(fn () => route('login'));

        if (! is_null($callback)) {
            $callback($middleware);
        }

        $kernel->setGlobalMiddleware($middleware->getGlobalMiddleware());
        $kernel->setMiddlewareGroups($middleware->getMiddlewareGroups());
        $kernel->setMiddlewareAliases($middleware->getMiddlewareAliases());
        // ...
    });

    return $this;
}
```

`withMiddleware()` voert de callback pas uit **nadat** de `HttpKernel` is geresolved, dankzij de `afterResolving()`-hook. Het `Middleware`-object dat aan de callback wordt doorgegeven heeft een rijke set aanpassingsmethodes.

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

    // Middleware toevoegen aan de web-groep
    $middleware->web(append: [EnsureUserIsSubscribed::class]);

    // Middleware in de api-groep vervangen
    $middleware->api(replace: [
        OldMiddleware::class => NewMiddleware::class,
    ]);

    // Paden uitzonderen van CSRF
    $middleware->validateCsrfTokens(except: ['stripe/*', 'webhook/*']);

    // Redirectdoel voor niet-geauthenticeerde gebruikers wijzigen
    $middleware->redirectGuestsTo('/custom-login');

    // Prioriteit van middleware instellen
    $middleware->priority([
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    ]);
})
```

### `withExceptions()` — exceptieafhandeling configureren

```php theme={null}
public function withExceptions(?callable $using = null)
{
    $this->app->singleton(
        \Illuminate\Contracts\Debug\ExceptionHandler::class,
        \Illuminate\Foundation\Exceptions\Handler::class
    );

    if ($using !== null) {
        $this->app->afterResolving(
            \Illuminate\Foundation\Exceptions\Handler::class,
            fn ($handler) => $using(new Exceptions($handler)),
        );
    }

    return $this;
}
```

`withExceptions()` registreert de `Handler`-klasse van het framework als singleton en stelt de callback in via `afterResolving()`. De callback krijgt een `Exceptions`-wrapperobject doorgegeven.

```php theme={null}
->withExceptions(function (Exceptions $exceptions) {
    // Bepaalde excepties niet rapporteren
    $exceptions->dontReport(MissedFlightException::class);

    // Bepaalde excepties op maat rapporteren
    $exceptions->report(function (InvalidOrderException $e) {
        // Bijvoorbeeld een melding naar Slack
    });

    // De HTTP-response voor bepaalde excepties aanpassen
    $exceptions->render(function (NotFoundHttpException $e, Request $request) {
        if ($request->is('api/*')) {
            return response()->json(['message' => 'Not Found'], 404);
        }
    });

    // Throttling (dezelfde exceptie niet steeds opnieuw rapporteren)
    $exceptions->throttle(function (Throwable $e) {
        return Limit::perMinute(20);
    });
})
```

### `withProviders()` — service providers registreren

```php theme={null}
public function withProviders(array $providers = [], bool $withBootstrapProviders = true)
{
    RegisterProviders::merge(
        $providers,
        $withBootstrapProviders
            ? $this->app->getBootstrapProvidersPath()
            : null
    );

    return $this;
}
```

`withProviders()` wordt standaard aangeroepen binnen `Application::configure()`, dus `bootstrap/providers.php` wordt automatisch ingeladen. Wil je extra providers doorgeven, dan moet je de methode expliciet aanroepen in `bootstrap/app.php`.

```php theme={null}
Application::configure(basePath: dirname(__DIR__))
    ->withProviders([
        // Providers toevoegen bovenop het standaard bootstrap/providers.php
        App\Providers\CustomServiceProvider::class,
    ])
    ->withRouting(...)
    ->create();
```

<Warning>
  Geef je `withBootstrapProviders: false` door, dan wordt `bootstrap/providers.php` niet meer ingeladen. Laat dit weg tenzij je er een bijzondere reden voor hebt.
</Warning>

### Overige belangrijke methodes

| Methode                              | Beschrijving                                                                                       |
| ------------------------------------ | -------------------------------------------------------------------------------------------------- |
| `withKernels()`                      | Registreert de HTTP-/consolekernel als singleton. Wordt automatisch aangeroepen door `configure()` |
| `withEvents()`                       | Schakelt event discovery in. Wordt automatisch aangeroepen door `configure()`                      |
| `withCommands(array $commands)`      | Registreert extra Artisan-commandklassen of -mappen                                                |
| `withSchedule(callable $callback)`   | Definieert de schedule in `bootstrap/app.php`                                                      |
| `withBroadcasting(string $channels)` | Registreert het bestand met broadcastkanalen                                                       |
| `withBindings(array $bindings)`      | Registreert containerbindings                                                                      |
| `withSingletons(array $singletons)`  | Registreert singletonbindings                                                                      |
| `registered(callable $callback)`     | Voegt een callback toe die wordt uitgevoerd na registratie van de service providers                |
| `booting(callable $callback)`        | Voegt een callback toe die wordt uitgevoerd tijdens het booten                                     |
| `booted(callable $callback)`         | Voegt een callback toe die wordt uitgevoerd na het booten                                          |
| `create()`                           | Geeft de `Application`-instantie terug                                                             |

## Ontwerpintentie: waarom is het zo opgezet?

### "Code-first"-configuratie

In `app/Http/Kernel.php` van Laravel 10 en eerder werd middleware opgesomd in arrays. Dat leek meer op een configuratiebestand, met als nadeel dat het typesysteem van PHP en IDE-ondersteuning weinig hielpen.

In Laravel 11 is dit veranderd in de callbackstijl `withMiddleware(function (Middleware $middleware) { ... })`. Daardoor werkt typeaanvulling en kun je op natuurlijke wijze dynamische configuratie schrijven met condities en lussen.

### Van "conventie boven configuratie" naar "expliciete configuratie"

Dat `api.php` opt-in is geworden, lost het probleem op dat de `api`-middlewaregroep altijd werd geladen, ook in applicaties die geen API-routes gebruiken. De filosofie: functionaliteit die je niet gebruikt, bestaat standaard niet.

### Slim gebruik van de `afterResolving()`-hook

Dat `withMiddleware()` en `withExceptions()` gebruikmaken van `afterResolving()` is om volgordeproblemen in de configuratie te vermijden. De methodes van de `ApplicationBuilder` worden aangeroepen voordat de applicatie volledig is opgestart, maar de daadwerkelijke verwerking (het toepassen van de configuratie op de kernel) wordt uitgesteld tot het moment waarop de kernel voor het eerst wordt geresolved.

## Praktijkvoorbeelden van aanpassingen

### API en web naast elkaar

```php theme={null}
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        apiPrefix: 'api/v1',  // gewijzigd ten opzichte van de standaard /api
    )
    ->withMiddleware(function (Middleware $middleware): void {
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
```

### Middleware aanpassen

```php theme={null}
->withMiddleware(function (Middleware $middleware) {
    // Middleware voor authenticatiecontrole toevoegen aan webroutes
    $middleware->web(append: [
        \App\Http\Middleware\EnsureEmailIsVerified::class,
    ]);

    // Bepaalde middleware uitsluiten op API-routes
    $middleware->api(remove: [
        \Illuminate\Session\Middleware\StartSession::class,
    ]);

    // Webhook-endpoints uitzonderen van CSRF
    $middleware->validateCsrfTokens(except: [
        'webhook/*',
        'stripe/webhook',
    ]);

    // Een alias instellen voor bepaalde middleware
    $middleware->alias([
        'subscribed' => \App\Http\Middleware\EnsureUserIsSubscribed::class,
    ]);
})
```

### De schedule samenbrengen in `bootstrap/app.php`

Je kunt de schedule in `routes/console.php` schrijven, maar met `withSchedule()` bundel je alles in `bootstrap/app.php`.

```php theme={null}
use Illuminate\Console\Scheduling\Schedule;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withSchedule(function (Schedule $schedule) {
        $schedule->command('emails:send')->daily();
        $schedule->command('reports:generate')->weeklyOn(1, '8:00');
        $schedule->job(new PruneOldRecords)->daily();
    })
    ->withMiddleware(function (Middleware $middleware): void {
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
```

### Exceptieafhandeling aanpassen

```php theme={null}
->withExceptions(function (Exceptions $exceptions) {
    // Bij API-requests altijd JSON teruggeven
    $exceptions->render(function (Throwable $e, Request $request) {
        if ($request->is('api/*') || $request->wantsJson()) {
            $status = match (true) {
                $e instanceof NotFoundHttpException => 404,
                $e instanceof AuthenticationException => 401,
                $e instanceof AuthorizationException => 403,
                $e instanceof ValidationException => 422,
                default => 500,
            };

            return response()->json([
                'message' => $e->getMessage(),
            ], $status);
        }
    });

    // Alleen in productie een melding naar Slack sturen
    if (app()->isProduction()) {
        $exceptions->report(function (Throwable $e) {
            app(SlackNotifier::class)->notify($e);
        })->stop();
    }
})
```

### Containerbindings beheren in `bootstrap/app.php`

Bij een kleine applicatie kun je simpele bindings ook in `bootstrap/app.php` zetten in plaats van in de `AppServiceProvider`.

```php theme={null}
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(...)
    ->withSingletons([
        \App\Contracts\PaymentGateway::class => \App\Services\StripeGateway::class,
        \App\Contracts\MailService::class => \App\Services\SendgridMailService::class,
    ])
    ->withMiddleware(...)
    ->withExceptions(...)
    ->create();
```

## De volgorde van het opstartproces van Laravel

Bij het opstarten van een Laravel-applicatie worden de service providers en de hooks van de Application in deze volgorde uitgevoerd:

1. Uitvoering van `register()` van alle ServiceProviders
2. `registered()` van de Application
3. `booting()` van de Application
4. Uitvoering van `boot()` van alle ServiceProviders
5. `booted()` van de Application

Voeg de volgende code toe aan de `AppServiceProvider` om de uitvoeringsvolgorde te bekijken.

```php theme={null}
class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        info('1. AppServiceProvider register');

        $this->booting(function () {
            info('4. AppServiceProvider booting');
        });

        $this->booted(function () {
            info('5. AppServiceProvider booted');
        });

        $this->app->registered(function () {
            info('2. app registered');
        });

        $this->app->booting(function () {
            info('3. app booting');
        });

        $this->app->booted(function () {
            info('6. AppServiceProvider@register app booted');
        });
    }

    public function boot(): void
    {
        $this->app->booted(function () {
            info('7. AppServiceProvider@boot app booted');
        });
    }
}
```

De methodes `registered()`, `booting()` en `booted()` van de `ApplicationBuilder` registreren alleen een callback bij de Application. Normaal heb je ze niet nodig, maar ze maken bijzondere handelingen mogelijk, zoals via `booted()` wijzigingen aanbrengen in de kernel nadat die klaar is met opstarten.

```php theme={null}
// bootstrap/app.php

use Illuminate\Contracts\Http\Kernel;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(...)
    ->withMiddleware(...)
    ->withExceptions(...)
    ->booted(function (Application $app) {
        $kernel = $app->make(Kernel::class);

        //

        $app->instance(Kernel::class, $kernel);
    })
    ->create();
```

## Volgende stappen

<Card title="Service container" icon="box" href="/nl/service-container">
  Begrijp de werking van de service container die de `ApplicationBuilder` intern gebruikt.
</Card>

<Card title="FAQ nieuwe appstructuur" icon="circle-question" href="/nl/advanced/app-structure-faq">
  Veelgestelde vragen en antwoorden over de nieuwe applicatiestructuur.
</Card>


## Related topics

- [FAQ over de nieuwe appstructuur van Laravel 11+](/nl/advanced/app-structure-faq.md)
- [Migratiegids van oude naar nieuwe structuur](/nl/advanced/app-structure-migration.md)
- [Upgraden van Laravel 10 naar 11](/nl/blog/upgrade-10-to-11.md)
- [Upgradegids van Laravel 11 naar 12](/nl/blog/upgrade-11-to-12.md)
- [Versiecompatibiliteit van packages beheren](/nl/advanced/package-versioning.md)
