Viele PHP-Anwendungen, die vor 2010 entstanden sind, kennen keine Klassen, keine Namespaces, keine Interfaces. Funktionen liegen in globalen Dateien, Variablen werden per global geteilt, Logik und Template sind untrennbar vermischt. Das ist prozedurales PHP – und es läuft oft seit Jahren stabil in Produktion, weil es schlicht niemand anfasst. Was in der Praxis der stabilste Deploymentprozess ist, den ich kenne.

Warum OOP der richtige Zielpunkt ist

Objektorientierung ist kein Selbstzweck und kein Statussymbol. Sie löst ein konkretes Problem: Kapselung. Wenn Logik in Klassen lebt, ist klar, was zusammengehört, was von außen sichtbar ist und was nicht. Das macht Testbarkeit möglich, Austauschbarkeit sinnvoll und Erweiterung sicher – ohne dass man jedes Mal das gesamte System im Kopf haben muss.

Der Migrationspfad: außen nach innen

Schritt 1: Namespaces einführen

Composer-Autoloading ist der erste Schritt. Mit einer PSR-4-Konfiguration in der composer.json werden neue Klassen automatisch geladen. Bestehende Funktionsdateien bleiben vorerst unangetastet – sie werden in autoload.files eingetragen und weiterhin global verfügbar gemacht. Niemand muss davon wissen.

Schritt 2: Klassen um bestehende Funktionen legen

Statt Funktionen sofort zu refactorn, werden sie in Klassen eingebettet. Eine Klasse UserService mit statischen Methoden, die intern die alten Funktionen aufrufen. Das ist kein schöner Code – aber es ist ein sicherer Zwischenschritt, der das Verhalten nicht ändert. Manchmal muss man hässlich durch die Tür, um auf der anderen Seite aufzuräumen.

Schritt 3: State kapseln

global-Variablen werden durch Konstruktor-Argumente oder Dependency Injection ersetzt. Dieser Schritt ist oft der aufwendigste, weil globaler Zustand schwer zu durchschauen ist und gerne überraschende Abhängigkeiten offenbart. Charakterisierungstests sind hier unverzichtbar.

Schritt 4: Logik von Template trennen

PHP-Dateien, die Logik und HTML mischen, werden aufgeteilt. Die Logik wandert in eine Klasse, das Template bekommt nur noch sauber vorbereitete Variablen übergeben. Twig oder Blade können schrittweise eingeführt werden.

Prozeduralen Code in OOP zu überführen ist kein Sprint. Es ist ein Marathon – und der erste Kilometer ist Namespaces.

Fazit

Die Migration von prozeduralem zu objektorientiertem PHP ist eine der langwierigsten, aber auch lohnendsten Aufgaben in der Legacy-Modernisierung. Wer sie schrittweise angeht, riskiert nichts und gewinnt mit jedem Schritt ein System, das ein bisschen testbarer, wartbarer und verständlicher ist als zuvor. Und irgendwann hört man auf, bei jedem global $db zusammenzuzucken.