Laravel Legacy Upgrade

Laravel Legacy Upgrade: waar de echte problemen beginnen

“Laten we Laravel upgraden” klinkt als een eenvoudige taak. Totdat je composer.json opent. Een legacy-project kan perfect draaien op Laravel 7 of 8, maar een upgrade naar een moderne versie kan een hele reeks aan compatibiliteitsproblemen aan het licht brengen.

Hier zijn enkele van de meest voorkomende bij een Laravel Legacy Upgrade:

1. Een package uit het oude project is niet compatibel met de nieuwe Laravel

Dit is waarschijnlijk het meest frustrerende scenario. De applicatie gebruikt een package dat perfect werkte op Laravel 8:

Laravel 8
└── package-x 2.4

Je upgradet naar Laravel 11:

Laravel 11
└── package-x 2.4 ❌

Composer weigert het te installeren omdat het package een oudere versie van illuminate/* vereist.

Nu moet je kiezen:

  • een nieuwere versie zoeken;
  • het package vervangen;
  • het forken en zelf onderhouden;
  • of de Laravel-upgrade uitstellen.

En soms wordt het package helemaal niet meer onderhouden (abandoned), waardoor er simpelweg geen upgradepad is.

2. Composer dependency-conflicten bij een Laravel Legacy Upgrade

Eén enkele upgrade kan conflicten op meerdere niveaus aan het licht brengen.
Bijvoorbeeld:

Laravel 11
   ↓
requires Symfony 7
   ↓
Package A requires Symfony 6
   ↓
Package B requires Package A

Composer kan niet aan al deze vereisten voldoen. Het frustrerende is dat het package dat het probleem veroorzaakt misschien niet eens iets is dat je direct gebruikt. Het kan een dependency van een andere dependency zijn. Dat is het moment waarop een simpele framework-upgrade verandert in dependency-archeologie.

3. composer.lock kan de oude dependency-tree vasthouden

Je werkt composer.json bij:

"laravel/framework": "^11.0"

Maar Composer meldt nog steeds conflicten omdat composer.lock versies uit de oude applicatie bevat. Het lock-bestand vertegenwoordigt de dependency-tree die eerder werd vastgelegd.

Daarom moet je soms niet alleen Laravel updaten, maar ook een zorgvuldig geselecteerde groep van gerelateerde dependencies — zonder blindelings composer.lock te verwijderen en te hopen op het beste.

4. De nieuwe Laravel-versie vereist een nieuwere PHP-versie

Bijvoorbeeld:
Oude applicatie

Laravel 8
PHP 7.4

wordt:

Laravel 11
PHP >= 8.2

Maar het upgraden van PHP kan een nieuwe laag aan problemen aan het licht brengen. Sommige oude packages ondersteunen PHP 8.2 misschien niet meer. Daardoor wordt de dependency-keten als volgt:

Laravel upgrade
      ↓
PHP upgrade
      ↓
old packages become incompatible
      ↓
packages need upgrading/replacing
      ↓
application code needs changes

5. Het package heeft een nieuwe versie — maar de API is veranderd

Dit is makkelijk te onderschatten. Je vindt een compatibele versie en Composer installeert deze succesvol. Geweldig.

Behalve dat de oude code:

SomePackage::process($data);

kan nu vereisen:

SomePackage::process($data, $options);

of de methode is mogelijk hernoemd of verwijderd, of het retourtype ervan is gewijzigd. Kortom: succes met Composer betekent niet automatisch succes voor de applicatie.

6. Symfony-upgrades kunnen Laravel-applicaties beïnvloeden

Laravel is sterk afhankelijk van Symfony-componenten. Wanneer Laravel overstapt op nieuwere Symfony-versies, kunnen custom code of packages die gebouwd zijn rondom ouder Symfony-gedrag stukgaan. Dit is met name relevant voor projecten met custom integraties, HTTP-afhandeling, console-commando’s, mail, events of filesystem-functionaliteit.

7. Flysystem-upgrades kunnen filesystem-integraties breken

Een goed voorbeeld hiervan is de overstap naar Flysystem 3. Een oude applicatie kan het volgende bevatten:

Laravel
└── Flysystem 1/2
    └── custom storage adapter

Na de upgrade:

Na de upgrade:

Laravel
└── Flysystem 1/2
    └── custom storage adapter

De Laravel-applicatie zelf kan dan wel compatibel zijn, maar een custom adapter of package die rondom de oude Flysystem-API is gebouwd, is dat mogelijk niet.

8. Authenticatie-packages hebben hun eigen upgradepaden

Laravel Passport, Sanctum, Socialite en andere ecosysteem-packages lopen niet per se synchroon met Laravel. Je kunt eindigen met:

Laravel → new version
Passport → old version
      ↓
incompatible dependencies

Of je kunt Passport upgraden en er vervolgens achter komen dat authenticatie-flows, configuraties of database-migraties aanpassingen nodig hebben.

9. Migraties van packages kunnen veranderen

Dit is weer zo’n subtiele. Een package kan correct geïnstalleerd zijn, maar de database-setup kan in een nieuwere versie anders werken. Je upgradet het package, deployt de applicatie en ontdekt plotseling dat verwachte tabellen, kolommen of indexen ontbreken. Daarom moeten package-upgrades worden behandeld als applicatiewijzigingen — en niet alleen als Composer-wijzigingen.

10. PHPUnit en de testsuite kunnen een volgende migratie worden

De productiecode ziet er misschien nog steeds prima uit. Dan run je:

php artisan test

en de helft van de testsuite faalt. Waarom? Omdat de door Laravel ondersteunde PHPUnit-versies in de loop der tijd veranderen en PHPUnit zelf verouderde API’s verwijdert. Een upgrade van Laravel kan dus betekenen dat je ook het volgende moet upgraden:

Laravel
+
PHP
+
Composer packages
+
PHPUnit
+
test code

11. Configuratie en applicatiestructuur kunnen veranderen

Een nieuwere Laravel-versie kan een andere standaardstructuur of configuratiebenadering introduceren. De verleiding is groot om een verse Laravel-installatie te nemen en alles naar het oude project te kopiëren. Dat is vaak een slecht idee. Een legacy-applicatie heeft jaren aan custom configuratie, middleware, service providers en integraties. Het doel is niet om de oude applicatie eruit te laten zien als een verse Laravel-installatie. Het doel is om de bestaande applicatie veilig over te zetten naar de nieuwe framework-versie.

En dit is wat Laravel-upgrades zo lastig maakt. Het probleem is zelden:
“Hoe installeer ik Laravel 11?”

Het echte probleem is:

“Welke delen van deze 7 jaar oude dependency-tree kunnen daadwerkelijk naar Laravel 11 worden gemigreerd zonder de applicatie te breken?”

Voordat ik ga upgraden, zou ik willen weten:

  • Voordat ik ga upgraden, zou ik willen weten:
  • Welke packages blokkeren de upgrade?
  • Welke packages zijn abandoned?
  • Welke packages moeten worden vervangen?
  • Welke PHP-versie is vereist?
  • Welke Symfony-/Flysystem-versies gaan veranderen?
  • Welke versies zet composer.lock momenteel vast?
  • Welke API’s hebben breaking changes?
  • Welke database-migraties worden geraakt?
  • Zal de bestaande testsuite nog steeds draaien?
  • Welke bedrijfskritische flows hebben regressietesten nodig?

Want in een legacy Laravel-applicatie is het upgradepad vaak gecompliceerder dan de upgrade zelf.

Wat is de grootste Laravel upgrade-blocker die jij bent tegengekomen — een incompatibel package, Composer-conflicten, PHP, of iets anders?

Lees meer: