Composer existiert seit 2012. Das sind 14 Jahre Dependency Management,
Autoloading und reproduzierbare Builds – für alle, die ihn verwenden.
Für alle anderen gibt es den Ordner libs/ mit irgendwelchen
kopierten Bibliotheken aus dem Jahr 2011, von denen niemand weiß,
ob sie noch aktuell sind, welche Version das war, oder wer sie damals
reinkopiert hat. Meistens war es jemand, der nicht mehr da ist.
Warum der Umstieg sich lohnt
Composer löst drei Probleme gleichzeitig: Autoloading, Versionierung
und Reproduzierbarkeit. Statt langer include-Ketten gibt
es einen einzigen require 'vendor/autoload.php'.
Statt manuell kopierten Bibliotheksversionen gibt es eine
composer.lock, die garantiert, dass alle Entwickler
und alle Server exakt dieselben Abhängigkeiten verwenden.
Klingt selbstverständlich. Ist es erstaunlich oft nicht.
Der Einstieg: Composer neben dem bestehenden Code
Der erste Schritt muss das bestehende System nicht verändern.
Composer wird installiert, eine composer.json wird angelegt,
und der Autoloader wird in den Front-Controller eingebunden –
zusätzlich zu den bestehenden Includes, nicht stattdessen.
Das verändert kein Verhalten, aber es schafft die Grundlage.
Niemand muss es wissen. Es funktioniert einfach.
PSR-4-Autoloading für eigenen Code
Der nächste Schritt ist Autoloading für den eigenen Code.
Ein Namespace – zum Beispiel App\ – wird auf ein
Verzeichnis gemappt. Neue Klassen, die dort entstehen, werden
automatisch geladen. Die alten require-Ketten
bleiben vorerst bestehen und werden schrittweise ersetzt,
wenn die jeweiligen Dateien ohnehin angefasst werden.
Bestehende Abhängigkeiten migrieren
Kopierte Bibliotheken werden schrittweise durch Composer-Pakete ersetzt.
Zunächst: Gibt es das Paket auf Packagist? Falls ja, wird die kopierte
Version entfernt und durch composer require ersetzt.
Falls nein, kann der Code als lokales Paket oder über ein VCS-Repository
eingebunden werden. Falls das Paket seit Jahren nicht mehr gepflegt wird:
willkommen im nächsten Refactoring-Projekt.
Composer einzuführen bedeutet nicht, alles auf einmal zu ändern. Es bedeutet, ab heute keine neuen Abhängigkeiten mehr zu kopieren.
Häufige Fallstricke
Namenskonflikte zwischen alten global definierten Klassen und neuen
Composer-Paketen sind das häufigste Problem. Hier hilft ein klarer
Namespace für den eigenen Code, der Konflikte von Anfang an vermeidet.
Außerdem: composer.lock gehört ins Repository –
immer, auch für Anwendungen, nicht nur für Bibliotheken.
Das ist keine Empfehlung, das ist Pflicht.
Fazit
Composer nachträglich einzuführen ist einer der Schritte mit dem besten Aufwand-Nutzen-Verhältnis in der Legacy-Modernisierung. Er öffnet die Tür zu modernen Bibliotheken, zu sauberem Autoloading und zu einem reproduzierbaren Build-Prozess – ohne das bestehende System von einem Tag auf den anderen zu verändern. Und man kann endlich aufhören, Bibliotheken zu kopieren wie im Jahr 2009.