Referenz Askallo
Legacy-PHP kontrolliert modernisiert
Eine über viele Jahre entwickelte PHP-Anwendung sollte auf eine neuere Laufzeitumgebung migriert werden. Die besondere Herausforderung: mehrere Tausend Dateien, individuelle Altlogik, keine einheitliche Framework-Struktur und Abweichungen zwischen vorhandenen Datenbankständen und dem tatsächlich eingesetzten Produktivcode. Unser Ziel war deshalb nicht nur ein Versionswechsel. Zunächst musste eine belastbare Grundlage geschaffen werden, auf der sich der bestehende Code reproduzierbar analysieren, kontrolliert verändern und zuverlässig prüfen lässt.
Unsere Vorgehensweise
Um eine sichere und reproduzierbare Arbeitsbasis zu schaffen, haben wir zunächst eine moderne Docker‑Umgebung entwickelt, bestehend aus:
- PHP 5.6 (Legacy‑Server) – zur Analyse des Ist‑Zustands
- PHP 7.4 (Zielsystem) – für die Migration und Funktionsvalidierung
- Tools‑Container für PHPStan, Rector, PHPCS & Composer
- MySQL‑ und Monitoring‑Services zur Umgebungssimulation
Parallel haben wir eine vollständige statische Code‑Analyse aufgebaut:
- PHPStan zur Identifikation von logischen Problemen, typischen Fallstricken und Migrationrisiken
- PHPCS + PHPCompatibility zur Erkennung von Funktionen und Strukturen, die unter PHP 7.x nicht mehr lauffähig sind
- Rector zur automatisierten Modernisierung und Vorbereitung des Codes auf PHP 7.4
#Starten des Analyse Containers
docker compose run --rm php-tools bash
#Einmalig:
composer install
composer require --dev phpcompatibility/php-compatibility
composer require --dev dealerdirect/phpcodesniffer-composer-installer
#PHPStan laufen lassen
vendor/bin/phpstan analyse --memory-limit=2G
# 1) Text-Report
vendor/bin/phpstan analyse --memory-limit=2G --error-format=table > phpstan-report.txt
# 2) JSON-Report (perfekt für später)
vendor/bin/phpstan analyse --memory-limit=2G --error-format=json > phpstan-report.json
# 3) Checkstyle/XML Report
# → gut für Editor‑Plugins
vendor/bin/phpstan analyse --memory-limit=2G --error-format=checkstyle > phpstan.xml
#PHPCS + Compatibility Check
vendor/bin/phpcs -p -d memory_limit=2G > phpcs-report.txt
# oder mit Fehlern / Ausgaben:
vendor/bin/phpcs -p -d memory_limit=2G 2>&1 | tee phpcs-report.txt
# mögliche Report-Arten:
# full
# summary
# source
# xml
# json
# checkstyle
# csv
# ... (weitere)
# Dann Aufruf (beispiele):
vendor/bin/phpcs -d memory_limit=2G --standard=PHPCompatibility --extensions=php --report=full --report-file=phpcs-full.txt
vendor/bin/phpcs -d memory_limit=2G --standard=PHPCompatibility --extensions=php --report=summary --report-file=phpcs-summary.txt
vendor/bin/phpcs -d memory_limit=2G --standard=PHPCompatibility --extensions=php --report=json --report-file=phpcs.json
# Rector Migration (dry-run)
vendor/bin/rector process --dry-run
Die Ausgangslage
Die bestehende Anwendung bestand aus mehreren tausend Dateien verteilt über unterschiedliche Verzeichnisse („htdocs“ und „include“), zahlreichen Individuallösungen und gewachsenen Legacy‑Strukturen. Während der Analyse zeigte sich, dass die vorliegenden Datenbank‑SQL‑Dateien nicht vollständig dem Stand des Produktivcodes entsprachen – es fehlten u. a. Tabellenfelder, die von aktuellen Modulen benötigt wurden. Auch beim Aufbau einer lokalen Testumgebung zeigten sich Besonderheiten im Login‑Bereich: Obwohl die Datenbank korrekt importiert wurde, wurden Login‑Versuche mit vorhandenen Testnutzern abgewiesen. Zusätzlich erfolgte eine automatische HTTPS‑Weiterleitung, obwohl diese serverseitig zunächst deaktiviert worden war. Diese Punkte machten deutlich, dass diverse Altlogiken und Konfigurationsabhängigkeiten im Projekt berücksichtigt werden müssen.
Durch zusätzliche Ausschlussregeln (z. B. für Third‑Party‑ oder Legacy‑Ordner) konnten wir eine effiziente und zielgerichtete Analyse sicherstellen.
Vier Werkzeuge mit einer klaren Aufgabe
Composer: Abhängigkeiten reproduzierbar machen
Composer bildete die technische Grundlage für die eingesetzten Analysewerkzeuge und deren Abhängigkeiten. Dadurch ließen sich die benötigten Versionen zentral definieren und innerhalb der Docker-Umgebung zuverlässig reproduzieren.
PHPCS und PHPCompatibility: Inkompatiblen Code erkennen
Mit PHPCS und dem PHPCompatibility-Regelwerk wurde der Bestand gezielt auf Sprachkonstrukte, Funktionen und Strukturen untersucht, die beim Wechsel von PHP 5.6 auf PHP 7.4 problematisch werden konnten. Damit entstand eine nachvollziehbare Arbeitsgrundlage für die notwendigen manuellen und automatisierten Anpassungen.
PHPStan: Verborgene Risiken sichtbar machen
PHPStan analysierte den Code, ohne ihn auszuführen. So konnten unter anderem unklare Typannahmen, nicht vorhandene Methoden oder Eigenschaften und weitere logische Auffälligkeiten frühzeitig erkannt werden. Die statische Analyse half dabei, kritische Bereiche zu identifizieren, bevor Änderungen am produktiven Verhalten vorgenommen wurden.
Rector: Modernisierung automatisieren
Rector übernahm geeignete, regelbasierte Änderungen am bestehenden PHP-Code. Wiederkehrende Anpassungen mussten dadurch nicht Datei für Datei manuell umgesetzt werden. Die automatisierten Änderungen wurden anschließend erneut analysiert und geprüft. So blieb die Migration kontrollierbar und nachvollziehbar.
Die Modernisierung erfolgte nicht durch ein einzelnes Tool, sondern durch eine aufeinander abgestimmte Analyse- und Refactoring-Kette.
Legacy-Code -> überprüfbaren Prozess
Modernisierungsprozess
Der entscheidende Mehrwert lag nicht allein in der Verwendung einzelner Werkzeuge. Durch ihr Zusammenspiel entstand ein wiederholbarer Modernisierungsprozess:
- bestehenden Zustand reproduzieren,
- Abhängigkeiten und Projektstruktur erfassen,
- Risiken und Inkompatibilitäten erkennen,
- geeignete Änderungen automatisieren,
- den veränderten Code erneut prüfen.
Third-Party- und nicht relevante Legacy-Verzeichnisse wurden über gezielte Ausschlussregeln von der Analyse getrennt. Dadurch konzentrierten sich die Auswertungen auf die tatsächlich zu bearbeitenden Bereiche.
Das Ergebnis
Die gewachsene Anwendung wurde in eine kontrollierbare technische Arbeitsumgebung überführt. Migrationsrisiken waren nicht länger nur implizit im Code verborgen, sondern konnten systematisch erfasst, priorisiert und bearbeitet werden.
Dadurch entstanden:
- eine reproduzierbare Entwicklungs- und Analyseumgebung,
- eine transparente Übersicht über kritische Codebereiche,
- ein automatisierter Prozess für wiederkehrende Modernisierungen,
- eine klare Grundlage für manuelle Anpassungen,
- und eine belastbare Ausgangsbasis für weitere PHP-Upgrades.
So wurde aus einem schwer einschätzbaren Legacy-System eine schrittweise modernisierbare Codebasis.
Screenshots
