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

# Upgradegids van Laravel 12 naar 13

> Het stappenplan voor de upgrade van Laravel 12 naar Laravel 13, met breaking changes, deprecated functies en de highlights van nieuwe functies.

## Inleiding

Laravel 13 is uitgebracht in maart 2026. Deze gids beschrijft de stappen om te upgraden van Laravel 12.x naar 13.x.

<Info>
  De geschatte tijd voor de upgrade is **ongeveer 10 minuten**. De impact van breaking changes op je applicatie hangt echter af van de omvang en de functies die je gebruikt.
</Info>

### Upgraden met AI

Je kunt de upgrade ook automatiseren met [Laravel Boost](https://github.com/laravel/boost). Boost is een first-party MCP-server die AI-assistenten stapsgewijze upgradeprompts biedt. Na installatie in je Laravel 12-applicatie kun je in Claude Code, Cursor, OpenCode, Gemini en VS Code het slash-commando `/upgrade-laravel-v13` gebruiken om de upgrade naar Laravel 13 te starten. Dit commando vereist `laravel/boost ^2.0`.

Ook met AI-tools die geen slash-commando's ondersteunen kun je dezelfde upgradestappen uitvoeren door direct naar het promptbestand te verwijzen. Plak de volgende prompt rechtstreeks in je AI.

```text prompt theme={null}
Lees de prompt die Laravel Boost aanbiedt en voer de upgrade van Laravel 12 naar 13 uit.
https://raw.githubusercontent.com/laravel/boost/refs/heads/main/src/Mcp/Prompts/UpgradeLaravelv13/upgrade-laravel-v13.blade.php

- Verwerk de wijzigingen in de `laravel/laravel`-skeleton. Controleer de branch 13.x, niet master.
- Wijzig `database/migrations/*_create_cache_table.php` niet direct, maar maak een nieuwe migratie aan.
- Zet `serialization` in `config/session.php` op `php`: `'serialization' => 'php'`
- De wijziging die op Laravel 13 de meeste fouten in apps veroorzaakt is het gewijzigde cachegedrag; doorzoek het project op cachegebruik en werk, als toestaan veilig lijkt, `serializable_classes` in config/cache.php bij.

'serializable_classes' => [
    App\Data\CachedDashboardStats::class,
    App\Support\CachedPricingSnapshot::class,
    Illuminate\Support\Collection::class,
    Illuminate\Database\Eloquent\Collection::class,
],
```

***

## Wijzigingen per impactniveau

### Impact: hoog

* Dependencies bijwerken
* De Laravel installer bijwerken
* Bescherming tegen request forgery (CSRF)

### Impact: middel

* De cache-instelling `serializable_classes`
* De sessie-instelling `serialization`

### Impact: laag

* Cacheprefix en naam van de sessiecookie
* Serialisatie van modelcollecties
* `Container::call` en nullable klasse-defaults
* Prioriteit van domeinrouteregistratie
* Exceptie-payload van het `JobAttempted`-event
* Binding van Manager `extend`-callbacks
* MySQL `DELETE`-queries (JOIN / ORDER BY / LIMIT)
* Bootstrap-viewnamen voor paginatie
* Generatie van polymorfe pivot-tabelnamen
* Hernoemde property van het `QueueBusy`-event
* Reset van de `Str`-factory tussen tests

***

## Upgradestappen

### Dependencies bijwerken

**Impact: hoog**

Werk de volgende dependencies in `composer.json` bij.

```json theme={null}
{
  "require": {
    "laravel/framework": "^13.0",
    "laravel/tinker": "^3.0"
  },
  "require-dev": {
    "phpunit/phpunit": "^12.0",
    "pestphp/pest": "^4.0"
  }
}
```

Gebruik je Laravel Boost, werk die dan ook bij.

```json theme={null}
{
  "require": {
    "laravel/boost": "^2.0"
  }
}
```

Installeer daarna de dependencies met het volgende commando.

```shell theme={null}
composer update
```

***

### De Laravel installer bijwerken

**Impact: hoog**

Gebruik je de Laravel installer CLI om nieuwe Laravel-applicaties aan te maken, werk hem dan bij naar een versie met Laravel 13.x-ondersteuning.

Geïnstalleerd via `composer global require`:

```shell theme={null}
composer global update laravel/installer
```

Gebruik je de gebundelde versie van [Laravel Herd](https://herd.laravel.com), werk Herd zelf dan bij naar de nieuwste release.

***

## Breaking changes

### Security

#### Bescherming tegen request forgery

**Impact: hoog**

De CSRF-middleware van Laravel is hernoemd van `VerifyCsrfToken` naar `PreventRequestForgery`. Daarnaast is er verificatie van de herkomst van de request toegevoegd op basis van de header `Sec-Fetch-Site`.

`VerifyCsrfToken` en `ValidateCsrfToken` blijven bestaan als deprecated aliassen, maar alle plekken die er direct naar verwijzen moeten worden bijgewerkt naar `PreventRequestForgery`. Let vooral op wanneer je de middleware uitsluit in tests of routedefinities.

```php theme={null}
use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;

// Laravel <= 12.x
->withoutMiddleware([VerifyCsrfToken::class]);

// Laravel >= 13.x
->withoutMiddleware([PreventRequestForgery::class]);
```

Ook in de middleware-configuratie-API is nu `preventRequestForgery(...)` beschikbaar.

***

### Cache

#### Cacheprefix en naam van de sessiecookie

**Impact: laag**

De standaardprefixen van de cache- en Redis-keys van Laravel gebruiken nu een suffix met streepjes. Ook gebruikt de standaardnaam van de sessiecookie nu `Str::snake(...)`.

De meeste applicaties stellen deze waarden expliciet in via de configuratiebestanden en worden dus niet geraakt door deze wijziging. Alleen applicaties die vertrouwen op de fallback-configuratie van het framework worden beïnvloed.

```php theme={null}
// Laravel <= 12.x
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_cache_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_database_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_session';

// Laravel >= 13.x
Str::slug((string) env('APP_NAME', 'laravel')).'-cache-';
Str::slug((string) env('APP_NAME', 'laravel')).'-database-';
Str::snake((string) env('APP_NAME', 'laravel')).'_session';
```

Om het eerdere gedrag te behouden, stel je de waarden expliciet in via het `.env`-bestand.

```ini theme={null}
CACHE_PREFIX=myapp_cache_
REDIS_PREFIX=myapp_database_
SESSION_COOKIE=myapp_session
```

#### De cache-instelling `serializable_classes`

**Impact: middel**

Aan de standaard `cache`-configuratie is de optie `serializable_classes` toegevoegd, met als default `false`. Dit voorkomt PHP-deserialisatie-gadget-chain-aanvallen wanneer de `APP_KEY` uitlekt.

Slaat je applicatie bewust PHP-objecten op in de cache, dan moet je de klassen die gedeserialiseerd mogen worden expliciet opsommen.

```php theme={null}
// config/cache.php
'serializable_classes' => [
    App\Data\CachedDashboardStats::class,
    App\Support\CachedPricingSnapshot::class,
],
```

Deserialiseerde je willekeurige cache-objecten, dan moet je migreren naar een expliciete klasse-toestemmingslijst of naar niet-objectgebaseerde cachepayloads (zoals arrays).

#### De sessie-instelling `serialization`

**Impact: laag**

In de applicatieskeleton van Laravel 13 (`laravel/laravel`) staat `serialization` in `config/session.php` nu op `json`. De interne default van het framework blijft echter `php`.

<Warning>
  Wijzig je deze instelling van `php` naar `json`, dan worden alle actieve gebruikerssessies ongeldig. Bovendien kunnen er fouten optreden in applicaties die PHP-objecten in de sessie opslaan.
</Warning>

Wil je tijdens de upgrade de actieve sessies behouden, stel deze instelling dan expliciet in op `php`. Slaat je applicatie geen PHP-objecten op in de sessie en is het geen probleem om gebruikers opnieuw te laten inloggen, dan kun je voor betere beveiliging overstappen op `json`.

```php theme={null}
// config/session.php
'serialization' => 'php',
```

Controleer vóór het inschakelen van JSON-serialisatie dat je applicatie geen PHP-objecten in de sessie opslaat.

***

### Container

#### `Container::call` en nullable klasse-defaults

**Impact: laag**

`Container::call` respecteert nu de standaardwaarden van nullable klasseparameters wanneer er geen binding bestaat (in lijn met het gedrag dat in Laravel 12 voor constructorinjectie werd geïntroduceerd).

```php theme={null}
$container->call(function (?Carbon $date = null) {
    return $date;
});

// Laravel <= 12.x: geeft een Carbon-instantie terug
// Laravel >= 13.x: geeft null terug
```

***

### Database

#### MySQL `DELETE`-queries

**Impact: laag**

Laravel compileert in de MySQL-grammatica nu volledige `DELETE ... JOIN`-queries inclusief `ORDER BY` en `LIMIT`.

In eerdere versies werden de clausules `ORDER BY` / `LIMIT` soms genegeerd bij een DELETE met JOIN. In Laravel 13 worden deze clausules opgenomen in de gegenereerde SQL. Daardoor kan bij sommige database-engines die deze syntaxis niet ondersteunen een `QueryException` optreden.

***

### Eloquent

#### Generatie van polymorfe pivot-tabelnamen

**Impact: laag**

Bij het afleiden van de tabelnaam van een polymorf pivot-model met een custom pivot-modelklasse genereert Laravel nu een meervoudsnaam.

Vertrouwde je op de eerdere afgeleide enkelvoudsnaam, definieer de tabelnaam dan expliciet in het pivot-model.

```php theme={null}
class RoleUser extends MorphPivot
{
    protected $table = 'role_user'; // Expliciet opgeven
}
```

#### Serialisatie van modelcollecties

**Impact: laag**

Wanneer een Eloquent-modelcollectie wordt geserialiseerd en hersteld (zoals bij jobs in de queue), worden eager geladen relaties nu voor de modellen hersteld.

Heb je code die erop vertrouwde dat relaties na deserialisatie niet bestonden, dan moet je die aanpassen.

***

### Queue

#### Exceptie-payload van het `JobAttempted`-event

**Impact: laag**

Het event `Illuminate\Queue\Events\JobAttempted` stelt nu via `$exception` een exceptie-object (of `null`) beschikbaar, in plaats van de eerdere boolean-property `$exceptionOccurred`.

```php theme={null}
// Laravel <= 12.x
if ($event->exceptionOccurred) {
    // Er trad een exceptie op
}

// Laravel >= 13.x
if ($event->exception !== null) {
    // Er trad een exceptie op
    $exception = $event->exception;
}
```

#### Hernoemde property van het `QueueBusy`-event

**Impact: laag**

De property `$connection` van het event `Illuminate\Queue\Events\QueueBusy` is hernoemd naar `$connectionName`, voor consistentie met de andere queue-events.

```php theme={null}
// Laravel <= 12.x
$event->connection;

// Laravel >= 13.x
$event->connectionName;
```

***

### Routing

#### Prioriteit van domeinrouteregistratie

**Impact: laag**

Routes met een expliciet domein krijgen bij het routematchen nu voorrang boven routes zonder domein.

Hierdoor werken catch-all-subdomeinroutes consistent, ook wanneer routes zonder domein eerder zijn geregistreerd.

***

### Support

#### Binding van Manager `extend`-callbacks

**Impact: laag**

Closures van custom drivers die via de `extend`-methode van een Manager zijn geregistreerd, worden nu gebonden aan de managerinstantie.

Als binnen die callbacks eerder een ander object (zoals de serviceproviderinstantie) als `$this` werd gebruikt, moet je die waarde nu via `use (...)` in de closure-capture opnemen.

```php theme={null}
// Laravel <= 12.x
Manager::extend('custom', function ($app) {
    return $this->createCustomDriver($app); // $this is de serviceprovider
});

// Laravel >= 13.x
$provider = $this;
Manager::extend('custom', function ($app) use ($provider) {
    return $provider->createCustomDriver($app);
});
```

#### Reset van de `Str`-factory tussen tests

**Impact: laag**

Laravel reset nu custom `Str`-factory's tijdens de teardown van tests.

Vertrouwde je erop dat custom UUID- / ULID- / random-string-factory's tussen testmethodes bleven bestaan, stel ze dan in bij elke betrokken test of in een setup-hook.

***

### Views

#### Bootstrap-viewnamen voor paginatie

**Impact: laag**

De interne viewnamen van de standaard Bootstrap 3-paginatie zijn nu expliciet.

```php theme={null}
// Laravel <= 12.x
pagination::default
pagination::simple-default

// Laravel >= 13.x
pagination::bootstrap-3
pagination::simple-bootstrap-3
```

Verwijs je direct naar de oude paginatieviewnamen, werk die dan bij.

***

## Deprecated functies

| Functie                            | Alternatief                  |
| ---------------------------------- | ---------------------------- |
| `VerifyCsrfToken`-middleware       | `PreventRequestForgery`      |
| `ValidateCsrfToken`-middleware     | `PreventRequestForgery`      |
| `JobAttempted::$exceptionOccurred` | `JobAttempted::$exception`   |
| `QueueBusy::$connection`           | `QueueBusy::$connectionName` |

***

## Toevoegingen aan contracts

**Impact: zeer laag**

Alleen relevant als je custom implementaties hebt.

### Het `Dispatcher`-contract

Aan het contract `Illuminate\Contracts\Bus\Dispatcher` is de methode `dispatchAfterResponse($command, $handler = null)` toegevoegd.

### Het `ResponseFactory`-contract

Aan het contract `Illuminate\Contracts\Routing\ResponseFactory` is de signature `eventStream` toegevoegd.

### Het `MustVerifyEmail`-contract

Aan het contract `Illuminate\Contracts\Auth\MustVerifyEmail` is `markEmailAsUnverified()` toegevoegd.

### Het `Queue`-contract

Aan het contract `Illuminate\Contracts\Queue\Queue` zijn de volgende methodes voor het inspecteren van de queuegrootte toegevoegd (voorheen alleen gedeclareerd in docblocks).

* `pendingSize`
* `delayedSize`
* `reservedSize`
* `creationTimeOfOldestPendingJob`

### De `Store` / `Repository`-contracts

Aan de cachecontracts is de methode `touch` toegevoegd voor het verlengen van de TTL.

```php theme={null}
// Illuminate\Contracts\Cache\Store
public function touch($key, $seconds);
```

***

## Highlights van nieuwe functies

### AI-geassisteerd upgraden (Laravel Boost)

Laravel Boost is de officiële MCP-server. In combinatie met een AI-editor kun je met het commando `/upgrade-laravel-v13` de upgrade semi-automatisch uitvoeren.

### Herkomstverificatie via de header `Sec-Fetch-Site`

De middleware `PreventRequestForgery` voert extra originverificatie uit op basis van de header `Sec-Fetch-Site`. Hiermee is de CSRF-bescherming versterkt.

### Veilige deserialisatie van de cache

Dankzij de instelling `serializable_classes` worden alleen toegestane klassen gedeserialiseerd. De beveiliging tegen PHP-deserialisatieaanvallen is hiermee verbeterd.

### `eventStream` voor SSE (Server-Sent Events)

Aan het `ResponseFactory`-contract is `eventStream` toegevoegd, wat de ondersteuning voor Server-Sent Events verbetert.

### Betere zichtbaarheid van queues

Met methodes zoals `pendingSize`, `delayedSize` en `reservedSize` op het `Queue`-contract kun je de status van je queues fijnmaziger monitoren.

***

## Veelvoorkomende migratieproblemen en oplossingen

### Probleem: CSRF-gerelateerde tests falen

**Symptoom:** tests die naar `VerifyCsrfToken` verwijzen falen met een class-not-found-fout.

**Oplossing:** werk alle verwijzingen bij naar `PreventRequestForgery`.

```php theme={null}
// Before
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
->withoutMiddleware([VerifyCsrfToken::class]);

// After
use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
->withoutMiddleware([PreventRequestForgery::class]);
```

### Probleem: objecten kunnen niet uit de cache worden hersteld

**Symptoom:** uit de cache opgehaalde data is `null` of er treedt een `UnserializationFailedException` op.

**Oplossing:** voeg de gebruikte klassen toe aan `serializable_classes` in `config/cache.php`, of zet de gecachete waarden om naar arrays.

```php theme={null}
'serializable_classes' => [
    App\Models\User::class,
    App\Data\SomeData::class,
],
```

### Probleem: een `JobAttempted`-listener werkt niet

**Symptoom:** `$event->exceptionOccurred` is `null` of geeft een fout over een ongedefinieerde property.

**Oplossing:** wijzig het naar `$event->exception !== null`.

```php theme={null}
// Before
if ($event->exceptionOccurred) { ... }

// After
if ($event->exception !== null) { ... }
```

### Probleem: sessies worden ongeldig

**Symptoom:** gebruikers worden na de upgrade uitgelogd.

**Oplossing:** de standaardnaam van de sessiecookie is gewijzigd. Stel `SESSION_COOKIE` expliciet in via `.env` om de eerdere waarde te behouden.

```ini theme={null}
SESSION_COOKIE=laravel_session
```

### Probleem: cachekeys worden niet gevonden

**Symptoom:** na de upgrade nemen cache-misses toe.

**Oplossing:** de cacheprefix is gewijzigd. Stel `CACHE_PREFIX` in via `.env` of leeg de cache.

```shell theme={null}
php artisan cache:clear
```

***

## Referenties

* [Officiële upgradegids (Engels)](https://laravel.com/docs/13.x/upgrade)
* [Diff van de laravel/laravel-repository (12.x → 13.x)](https://github.com/laravel/laravel/compare/12.x...13.x)
* [Laravel Shift](https://laravelshift.com) — communitydienst die upgrades automatiseert
* [Laravel Boost](https://github.com/laravel/boost) — MCP-server voor AI-geassisteerd upgraden


## Related topics

- [Upgradegids van Laravel 11 naar 12](/nl/blog/upgrade-11-to-12.md)
- [Upgraden van Laravel 9 naar 10](/nl/blog/upgrade-9-to-10.md)
- [Upgraden van Laravel 8 naar 9](/nl/blog/upgrade-8-to-9.md)
- [Upgraden van Laravel 10 naar 11](/nl/blog/upgrade-10-to-11.md)
