Veraltete PHP-Abhängigkeiten sicher aktualisieren

PHP Abhängigkeiten aktualisieren, ohne die Anwendung zu zerreißen: ein pragmatischer Weg für gewachsene Systeme, bei denen ein großer Sprung keine Option ist.

Ein Blick in die composer.lock einer gewachsenen PHP-Anwendung ist oft ein Blick in die Vergangenheit: Pakete zwei Major-Versionen hinterher, ein Framework, das keine Sicherheitsupdates mehr bekommt, dazwischen zwei, drei Bibliotheken, deren Maintainer längst aufgehört haben. Der Reflex ist bekannt: "Das lohnt sich nicht mehr, das schreiben wir neu." Doch das System läuft seit Jahren, verdient Geld und bildet Fachlogik ab, die niemand mehr vollständig im Kopf hat. Nicht der alte Code ist das eigentliche Problem, sondern die Schicht drumherum, die niemand mehr anfassen will. Genau diese Schicht lässt sich aktualisieren, ohne bei null anzufangen.

Warum sollten Sie veraltete PHP-Abhängigkeiten überhaupt aktualisieren?

Veraltete Abhängigkeiten sind selten ein kosmetisches Problem, sondern ein Sicherheits- und Wartungsrisiko: ungepatchte Lücken, fehlende Kompatibilität zu neuen PHP-Versionen und Bibliotheken, die niemand mehr installieren kann.

Konkret gerät man in drei Klemmen. Erstens bekommen alte Framework- und Paketversionen keine Security-Fixes mehr, während bekannte Schwachstellen öffentlich dokumentiert sind. Zweitens zwingt der Hoster früher oder später auf eine neuere PHP-Version, und dann startet die alte Anwendung schlicht nicht mehr. Drittens wird jede kleine Anpassung teuer, weil man sich durch eine Codebasis kämpft, die von keinem aktuellen Werkzeug mehr unterstützt wird. Der richtige Zeitpunkt zum Handeln ist deshalb nicht "wenn etwas kaputt ist", sondern solange das System noch stabil läuft und Sie in Ruhe arbeiten können.

Bestandsaufnahme: Was steckt wirklich in Ihren Abhängigkeiten?

Bevor Sie irgendetwas anfassen, brauchen Sie ein ehrliches Bild vom Ist-Zustand. Composer liefert dafür die wichtigsten Werkzeuge bereits mit.

  • composer outdated --direct zeigt, welche Ihrer direkten Abhängigkeiten hinterherhinken. Die Beschränkung auf direkte Pakete verhindert, dass Sie sich in transitiven Abhängigkeiten verlieren, die Sie ohnehin nicht steuern.
  • composer audit gleicht Ihre installierten Versionen gegen die bekannte Schwachstellendatenbank ab. Das ist Ihre Prioritätenliste: Was hier auftaucht, ist ein Sicherheitsproblem, kein Nice-to-have.
  • composer why paket/name beantwortet die entscheidende Frage, warum ein Paket überhaupt installiert ist und wer es blockiert.

Notieren Sie sich zusätzlich, welche PHP-Version die Anwendung aktuell verlangt (composer why-not php 8.3 ist hier aufschlussreich). Oft ist nicht das Paket das Nadelöhr, sondern eine veraltete PHP-Anforderung, die einen ganzen Rattenschwanz nach sich zieht.

Wie aktualisieren Sie PHP-Abhängigkeiten, ohne die Anwendung zu zerreißen?

Die kurze Antwort: in kleinen, umkehrbaren Schritten statt in einem großen Sprung. Jeder Schritt wird einzeln getestet und committet, damit Sie bei einem Problem genau wissen, welche Änderung es ausgelöst hat.

Der teuerste und riskanteste Weg ist der, den viele zuerst einschlagen: composer update ohne Argumente, alles auf einmal. Wenn danach etwas bricht, stehen Sie vor Dutzenden gleichzeitig geänderten Paketen und haben keine Chance, die Ursache einzugrenzen. Gehen Sie stattdessen so vor:

  1. Patch- und Minor-Updates zuerst. Aktualisieren Sie zunächst nur innerhalb kompatibler Versionsbereiche: composer update --with-dependencies für einzelne, klar umrissene Pakete. Diese Updates versprechen nach Semantic Versioning keine Breaking Changes und holen Sie trotzdem an viele Sicherheitspatches heran.
  2. Ein Major-Upgrade pro Durchgang. Für einen Versionssprung heben Sie die Einschränkung in der composer.json gezielt für ein Paket an, führen composer update paket/name --with-dependencies aus und testen ausschließlich diesen einen Sprung.
  3. Changelog lesen, nicht raten. Bei jedem Major-Schritt gehört das UPGRADE.md beziehungsweise der Changelog des Pakets auf den Tisch. Dort stehen entfernte Methoden, geänderte Signaturen und Migrationshinweise, die Sie sonst erst zur Laufzeit entdecken.
  4. Nach jedem Schritt committen. Ein sauberer Commit pro Upgrade macht jeden Schritt einzeln umkehrbar. Das ist Ihr Sicherheitsnetz.

Das Sicherheitsnetz: Tests, statische Analyse und ein Rollback-Plan

Updates ohne Prüfnetz sind Glücksspiel. Der Punkt ist nicht, eine perfekte Testabdeckung nachzurüsten, sondern die kritischen Pfade abzusichern, bevor Sie Versionen anheben.

Statische Analyse ist dabei Ihr wirksamstes Werkzeug, gerade wenn es kaum Tests gibt. Ein Werkzeug wie PHPStan oder Psalm findet nach einem Upgrade sofort verschwundene Klassen, geänderte Rückgabetypen und falsche Aufrufe, ohne dass eine einzige Zeile Code ausgeführt werden muss. Legen Sie vor dem ersten Upgrade eine Baseline an, dann sehen Sie danach exakt die neu entstandenen Fehler. Ergänzend zeigt Rector viele durch Upgrades nötige Codeanpassungen automatisiert an und kann sie in Teilen anwenden, etwa bei Symfony- oder Laravel-Sprüngen.

Für die Fachlogik, die Geld bewegt oder Daten schreibt, lohnt sich vor dem Upgrade mindestens ein grober Smoke-Test oder ein paar gezielte Integrationstests. Genau diese seit Jahren funktionierende Logik ist der Beweis, dass das System trägt. Sie wollen sie beim Modernisieren nicht versehentlich beschädigen, sondern konservieren.

Framework-Sprünge bei Symfony und Laravel richtig planen

Bei Frameworks wie Symfony und Laravel ist die Reihenfolge entscheidend: Erst das Framework selbst auf die nächste unterstützte Version heben, dann die Ökosystem-Pakete nachziehen, niemals umgekehrt.

Ein häufiger Fehler ist der Versuch, zwei Major-Versionen in einem Rutsch zu überspringen. Beide Ökosysteme sind darauf ausgelegt, Version für Version zu wandern: Symfony pflegt für jeden Sprung ein UPGRADE-x.0.md, Laravel eine detaillierte Upgrade-Anleitung pro Release. Halten Sie sich an diese Kette. Deprecation-Meldungen sind dabei kein Rauschen, sondern Ihre Wegbeschreibung: Alles, was in der aktuellen Version als deprecated markiert ist, verschwindet in der nächsten. Wer die Deprecations vor dem Sprung abarbeitet, hat den Major-Upgrade schon halb geschafft.

Häufige Stolperfallen beim Aktualisieren von PHP-Paketen

  • Aufgegebene Pakete: Taucht ein "abandoned"-Hinweis auf, hilft kein Update. Suchen Sie den empfohlenen Nachfolger oder kapseln Sie die Funktion hinter einer eigenen kleinen Schnittstelle, damit der Austausch später an einer Stelle passiert.
  • Auf eigene Faust geforkte Bibliotheken: In alten Projekten liegt gelegentlich eine manuell veränderte Vendor-Bibliothek. Diese Änderungen müssen Sie kennen, bevor Sie sie mit einem Update überschreiben.
  • Die Erweiterungen des PHP-Servers: Ein Paket kann eine neuere PHP-Extension verlangen. Prüfen Sie die Serverumgebung, nicht nur die composer.json.

Praxis-Tipp zum Schluss

Fangen Sie klein an: Führen Sie heute composer audit aus und beheben Sie ausschließlich die Sicherheitsbefunde, ein Paket nach dem anderen, jeweils mit eigenem Commit. Dieser eine Durchgang bringt Ihnen den größten Sicherheitsgewinn bei kleinstem Risiko und zeigt Ihnen ehrlich, wie belastbar Ihre Codebasis auf Änderungen reagiert. Alles Weitere baut auf diesem ersten Schritt auf. Wenn ein Upgrade an einer besonders verwachsenen Stelle festhängt, ist es meist die Schicht um die Fachlogik herum, die den Weg versperrt, nicht die Logik selbst. Genau bei solchen festgefahrenen Modernisierungen unterstütze ich mit LegacyWerk, wenn Sie an einem Punkt nicht weiterkommen.

Sicher aktualisieren: ein Schritt nach dem anderen 1. Audit composer audit Lücken finden 2. Baseline PHPStan / Tests Netz spannen 3. Minor Patches ziehen kompatibel 4. Major 1 Paket / Durchgang Changelog lesen 5. Commit umkehrbar klein, getestet, jederzeit zurückrollbar

Minimal-Migration: ab 9.800 €, 2–6 Wochen

Nur das, was nötig ist, damit Ihr System wieder auf einer unterstützten PHP- und Framework-Version läuft. Sie schildern mir Ihr System in drei kurzen Schritten, ich antworte mit einer ehrlichen Einschätzung und einem Festpreis.

Minimal-Migration anfragen