Skip to main content

Inleiding

Laravel 13 is uitgebracht in maart 2026. Deze gids beschrijft de stappen om te upgraden van Laravel 12.x naar 13.x.
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.

Upgraden met AI

Je kunt de upgrade ook automatiseren met 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.
prompt

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.
Gebruik je Laravel Boost, werk die dan ook bij.
Installeer daarna de dependencies met het volgende commando.

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:
Gebruik je de gebundelde versie van Laravel Herd, 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.
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.
Om het eerdere gedrag te behouden, stel je de waarden expliciet in via het .env-bestand.

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

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.

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.

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.

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.

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.
Verwijs je direct naar de oude paginatieviewnamen, werk die dan bij.

Deprecated functies


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.

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.

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.

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.

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.

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.

Referenties

Laatst gewijzigd op 6 september 2026