Eine Anwendung läuft seit Jahren stabil auf PHP 5.6, verdient Geld und tut, was sie soll. Trotzdem wird sie zum Risiko: keine Sicherheitsupdates mehr, moderne Bibliotheken lassen sich nicht installieren, Hoster kündigen die alten Umgebungen. Dann fällt der Satz, der die meisten Projekte teuer macht: "Das schreiben wir am besten neu." In den allermeisten Fällen ist das die falsche Entscheidung. Wenn Ihr System jahrelang funktioniert, ist das der Beweis, dass die Fachlogik stimmt. Das Problem ist fast nie die Logik, sondern der Code drumherum. Genau den kann man reparieren, ohne bei null anzufangen.
Dieser Artikel beschreibt den realistischen Weg, wie Sie PHP 5.6 auf PHP 8 migrieren, ohne den Betrieb zu gefährden und ohne das Budget einer Neuentwicklung.
Warum PHP 5.6 auf PHP 8 migrieren und nicht neu bauen?
Eine Migration überführt bestehende, erprobte Logik in eine wartbare Umgebung. Eine Neuentwicklung wirft diese Logik weg und baut sie unter Zeitdruck neu — inklusive aller Sonderfälle, die über Jahre stillschweigend eingebaut wurden. Diese undokumentierten Sonderfälle sind der eigentliche Wert der Anwendung, und sie sind das, was bei einem Rewrite zuerst verloren geht.
Die Sprünge von PHP 5.6 zu 7.0 und von 7.x zu 8.0 sind die einzigen mit nennenswerten Breaking Changes. Dazwischen ist erstaunlich viel abwärtskompatibel. Der Aufwand ist also überschaubar und vor allem planbar — anders als bei einer Neuentwicklung, deren Ende selten dort liegt, wo es geplant war.
Wie sieht der realistische Migrationspfad aus?
Springen Sie nicht direkt von 5.6 auf 8.3. Gehen Sie in Stufen, weil jede Stufe eine eigene Klasse von Fehlern aufdeckt. Ein bewährter Pfad ist 5.6 auf 7.4, dann 7.4 auf 8.x. PHP 7.4 ist die letzte Version, die vieles aus der 5er-Zeit noch mit Deprecation-Warnungen toleriert, statt hart zu brechen. So trennen Sie die Fehlerquellen sauber voneinander.
- Bestandsaufnahme: Welche PHP-Version, welche Frameworks (Symfony, Laravel, ein Eigenbau?), welche Extensions, welche Datenbank, welche Composer-Abhängigkeiten und in welchen Versionen?
- Sicherheitsnetz bauen: Ohne Tests keine sichere Migration. Wenn keine da sind, schreiben Sie zuerst grobe Integrations- oder Smoke-Tests für die kritischen Geschäftsprozesse.
- 5.6 auf 7.4: Statische Analyse laufen lassen, Fehler beheben, Tests grün bekommen, ausliefern.
- 7.4 auf 8.x: Denselben Zyklus wiederholen, diesmal mit dem strengeren Typsystem von PHP 8.
Welche Breaking Changes treffen Sie zuerst?
Beim Schritt auf PHP 7 sind es meist diese: Die alte mysql_*-Erweiterung ist entfernt — Sie brauchen mysqli oder besser PDO. Alte Konstruktoren nach Klassennamen (function Klassenname()) funktionieren nicht mehr, es muss __construct() sein. Und each() sowie einige globale Variablen fallen weg.
Beim Schritt auf PHP 8 kommt der härtere Teil. Viele Warnungen sind jetzt Error-Exceptions: Ein Zugriff auf ein nicht existierendes Array-Element oder eine undefinierte Variable, der früher stillschweigend null lieferte, kann Ihren Ablauf jetzt stoppen. Der Operator-Vorrang bei Verkettung hat sich geändert, und die Signaturen interner Funktionen sind strenger geworden. Das klingt bedrohlich, ist aber gut beherrschbar, weil Werkzeuge diese Stellen finden, bevor ein Nutzer sie findet.
Welche Werkzeuge nehmen Ihnen die Arbeit ab?
Sie müssen nicht jede Zeile von Hand prüfen. Diese drei Werkzeuge tragen die Hauptlast:
- PHPCompatibility: Ein Regelsatz für PHP_CodeSniffer, der Ihren Code gegen eine Zielversion prüft und inkompatible Stellen meldet, ohne dass Sie den Code ausführen.
- Rector: Führt automatisierte Refactorings durch. Rector kann viele der genannten Breaking Changes selbst umschreiben — von Konstruktoren bis zu geänderten Funktionssignaturen. Prüfen Sie jede Änderung im Diff, aber lassen Sie die stumpfe Fleißarbeit die Maschine machen.
- PHPStan oder Psalm: Statische Analyse deckt genau die Typprobleme auf, die PHP 8 zur Laufzeit bestrafen würde. Starten Sie auf einem niedrigen Level und erhöhen Sie es schrittweise.
Ein realistischer Ablauf: Rector macht den groben Umbau, PHPStan zeigt die verbleibenden Schwachstellen, Ihre Tests bestätigen, dass die Fachlogik unverändert funktioniert.
Was ist mit dem Framework und den Abhängigkeiten?
Oft ist nicht Ihr eigener Code der Engpass, sondern eine veraltete Bibliothek in der composer.json. Prüfen Sie mit composer why, warum ein altes Paket eingebunden ist. Manchmal hängt ein längst nicht mehr benötigtes Feature an einer Abhängigkeit, die die ganze Migration blockiert.
Bei Frameworks ist Ehrlichkeit gefragt: Ein altes Symfony oder Laravel muss ebenfalls angehoben werden, und deren Upgrade-Pfade haben eigene Zwischenstufen. Ein selbstgebautes Framework aus der 5.6-Zeit kann sogar einfacher sein, weil es keine fremden Upgrade-Regeln erzwingt — dafür fehlt ihm die Dokumentation. Beides ist machbar. Beides sollten Sie einplanen, bevor Sie starten, nicht mittendrin entdecken.
Warum ist die Datenbank ein eigener Prüfpunkt?
Beim Wechsel der PHP-Version ändert sich häufig auch das Verhalten des Datenbanktreibers. Der Sprung von mysql_* auf PDO ändert, wie NULL-Werte und Zahlentypen zurückgegeben werden. Code, der sich auf lockere Typvergleiche verlassen hat, verhält sich danach anders. Testen Sie deshalb gezielt die Stellen, an denen Werte aus der Datenbank in Bedingungen einfließen.
Wie halten Sie das Risiko im Betrieb klein?
Migrieren Sie in einem eigenen Branch und richten Sie eine Staging-Umgebung mit der Zielversion ein, die der Produktion so nah wie möglich kommt. Schalten Sie display_errors auf Staging voll auf und protokollieren Sie alles, damit stillschweigende Deprecations sichtbar werden. Rollen Sie erst aus, wenn die kritischen Geschäftsprozesse dort grün durchlaufen. Ein Rollback-Plan gehört dazu, bevor der erste Nutzer auf die neue Version trifft.
Häufige Frage: Wie lange dauert es, PHP 5.6 auf PHP 8 zu migrieren?
Das hängt von der Codemenge, den Tests und den Abhängigkeiten ab, nicht von der PHP-Version selbst. Eine mittelgroße Anwendung mit brauchbarer Testabdeckung ist in Wochen machbar; ohne Tests kostet zuerst das Sicherheitsnetz Zeit. Seriös lässt sich das erst nach der Bestandsaufnahme beziffern.
Praxis-Tipp zum Schluss
Fangen Sie nicht mit dem Code an, sondern mit dem Sicherheitsnetz. Der teuerste Fehler bei einer Migration ist nicht ein übersehener Breaking Change — den findet ein Werkzeug. Der teuerste Fehler ist, eine stillschweigende Verhaltensänderung erst in der Produktion zu bemerken. Wer zuerst Tests für die kritischen Abläufe schreibt und dann in kleinen, auslieferbaren Schritten migriert, kommt fast immer schneller und billiger ans Ziel als jedes Neuentwicklungsprojekt. Genau bei solchen Migrationen von 5.6 auf 8 unterstützt LegacyWerk, wenn intern die Zeit oder die Erfahrung mit dem alten Code fehlt.