Refactoring von Legacy-Code in PHP: Von A bis Z
Die Arbeit mit Legacy-Code ist ein unvermeidlicher Teil des Lebens eines jeden PHP-Entwicklers. Früher oder später werden Sie auf ein Projekt stoßen, das in PHP 5.6 (oder sogar 4) geschrieben wurde, ohne Autoloading, mit globalen Variablen und einer Geschäftslogik, die mit HTML vermischt ist. Das Refactoring solchen Codes ist nicht nur "Kosmetik", sondern ein strategischer Prozess, der das Projekt vor technischen Schulden bewahren und wartbar machen kann.
In diesem Artikel zeigen wir, wie Sie systematisch an das Refactoring von Legacy-PHP-Code herangehen, ohne die funktionierende Funktionalität zu zerstören, und wie Sie das "Sumpfgebiet" in modernen, testbaren Code verwandeln.
1. Diagnose und Bewertung: Wo anfangen?
Bevor Sie den Code ändern, müssen Sie verstehen, womit Sie es zu tun haben. Beginnen Sie mit einem Audit des Projekts.
Schritt 1: Identifizieren Sie die "Schwachstellen"
- Abhängigkeiten: Werden veraltete Bibliotheken verwendet? Zum Beispiel
mysql_*-Funktionen anstelle von PDO oder MySQLi. - Architektur: Gibt es überhaupt eine Struktur (MVC)? Oder befindet sich der gesamte Code in einer einzigen Datei
index.php? - Tests: Gibt es automatisierte Tests? Wenn nicht, ist dies Ihre oberste Priorität.
Schritt 2: Analyse-Tools
Verwenden Sie statische Analysatoren, um Problemstellen schnell zu identifizieren:
- PHPStan / Psalm: Finden Typfehler und Signatur-Inkonsistenzen.
- Rector: Aktualisiert die Syntax automatisch auf eine neuere PHP-Version.
- PhpMetrics: Zeigt die zyklomatische Komplexität und Kohäsion des Codes.
Beispiel für die Ausführung von Rector zur Aktualisierung von PHP 7.4 auf 8.0:
vendor/bin/rector process src/ --set php802. Strategie "Schmerzfreie Chirurgie": Schritt-für-Schritt-Plan
Das Refactoring von Legacy-Code ist keine "große Explosion". Es ist eine Reihe kleiner, sicherer Schritte. Verwenden Sie die "Strangler-Fig"-Technik – ersetzen Sie alte Module schrittweise durch neue, ohne alles auf einmal umzuschreiben.
Schritt 1: Decken Sie den Code mit Tests ab
Ohne Tests ist Refactoring russisches Roulette. Beginnen Sie mit Charakterisierungstests (characterization tests):
class LegacyCalculatorTest extends TestCase { public function testOldCalculation(): void { // Alten Code ausführen und Ergebnis erfassen $result = legacy_calculation(10, 5); $this->assertEquals(15, $result); }}Dies schafft ein "Sicherheitsnetz" vor den Änderungen.
Schritt 2: Isolieren Sie die "schmutzige" Logik
Wenn der Code mit globalen Variablen arbeitet ($GLOBALS), extrahieren Sie diese in Funktionsparameter:
// Vorher (globale Abhängigkeit)function processOrder() { global $db; $result = $db->query("SELECT * FROM orders");}
// Nachher (Abhängigkeitsinjektion)function processOrder(PDO $db) { $result = $db->query("SELECT * FROM orders");}Schritt 3: Ersetzen Sie veraltete Funktionen
Zum Beispiel Ersetzung von mysql_* durch PDO:
// Alter Code$link = mysql_connect('localhost', 'user', 'pass');mysql_select_db('test', $link);$result = mysql_query("SELECT * FROM users", $link);
// Neuer Code (PDO)$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');$stmt = $pdo->query("SELECT * FROM users");$result = $stmt->fetchAll(PDO::FETCH_ASSOC);3. Typische Probleme von Legacy-PHP und deren Lösungen
Problem 1: "Spaghetti-Code" (Vermischung von Logik und Darstellung)
Lösung: Trennen Sie den Code in Schichten. Extrahieren Sie die Geschäftslogik in separate Klassen und das HTML in Vorlagen (z. B. mit Twig).
// Schlecht: Logik und HTML in einer Dateiif ($user->isAdmin()) { echo "<h1>Hallo, Admin!</h1>";} else { echo "<h1>Hallo, Benutzer!</h1>";}
// Gut: Controller + Vorlage//