Sprechen wir das Unausgesprochene aus: Das Makefile in deinem PHP-Projekt ist eine zweite Codebasis, geschrieben in einer Sprache, die in deinem Team niemand wirklich beherrscht, zusammengehalten von Tab-Zeichen und Stack-Overflow-Antworten von 2011. Wir reden uns ein, das sei okay, weil es ja 'nur Automatisierung' ist. Es ist nicht okay. Es ist ungetestete, ungereviewete Logik, die entscheidet, wie du deployst, migrierst und neu baust — und sobald sie ein if-Statement braucht, schraubt jemand ein Shell-Skript dran, und plötzlich pflegst du drei Sprachen, um eine auszuliefern. Meine Position: Wenn dein Projekt PHP ist, sollte dein Task-Runner es auch sein, und Castor ist das erste Tool, das dieses Argument überzeugend vertritt.
Der Pitch ist fast verdächtig simpel. Du schreibst ganz normale PHP-Funktionen in eine castor.php-Datei, klatschst ein #[AsTask]-Attribut drauf, und Castor macht aus jeder einzelnen ein CLI-Kommando. Die Funktionssignatur wird zum Interface: Pflichtparameter werden zu positionalen Argumenten, optionale zu Options, und mit Attributen wie #[AsArgument] und #[AsOption] überschreibst du die Defaults, wenn die Konvention nicht passt. Kein YAML, keine DSL, kein Registrierungs-Boilerplate. Wenn du je ein Symfony-Console-Kommando von Hand verdrahtet hast, fühlt sich das an, als hätte endlich jemand das Zeremoniell entfernt und das Ergebnis behalten.
Was mich überzeugt hat, ist aber nicht die Syntax — es ist der Unterbau. Castor ist eine dünne Schicht über Komponenten, denen die meisten von uns ohnehin vertrauen: Symfony Console für die CLI, Symfony Process hinter run(), Filesystem und Finder hinter fs(), nikic/php-parser zum Auffinden deiner Tasks, spatie/ssh für Remote-Ausführung, jolicode/jolinotif für Desktop-Benachrichtigungen. Das zählt in der Praxis. Wenn dein Rebuild-Task spinnt, debuggst du Symfony-Process-Semantik, die du bereits verstehst, statt zu entschlüsseln, warum Make stillschweigend einen Exit-Code verschluckt hat. Und wenn ein Task wirklich Logik braucht — eine wacklige Migration wiederholen, über Services loopen, bei einer schlechten Response eine Exception werfen — schreibst du das PHP, das du überall sonst schreiben würdest, mit echten Exceptions statt &&-Ketten und gedrückten Daumen.
Die Dependency-Geschichte verdient eine eigene Erwähnung, weil sie genau das repariert, was 'schreib's halt in PHP'-Ansätze sonst vergiftet. Castor führt sein eigenes Manifest — castor.composer.json und castor.composer.lock — und installiert Task-Abhängigkeiten nach .castor/vendor/, komplett getrennt von der composer.json deiner Anwendung. Ein castor composer require some/package verschafft deiner Automatisierung einen HTTP-Client oder einen YAML-Parser, ohne die Produktions-Dependencies zu verschmutzen oder einen Streit über Plattform-Requirements loszutreten. Du brauchst stattdessen ein einmaliges CLI-Tool? castor execute friendsofphp/php-cs-fixer fix lädt es herunter und führt es aus, ohne irgendein Manifest anzufassen. Diese Trennung ist der Unterschied zwischen einem Spielzeug und etwas, das du in einem Code-Review verteidigen kannst.
Jetzt das ehrliche Gegenargument, denn es ist ein starkes: Make ist überall. Es ist auf jedem CI-Runner, jeder Ops-Kiste, dem Rechner jeder Kollegin, und es wird auch in zwanzig Jahren noch da sein. Ein make deploy braucht null Onboarding; castor deploy braucht erst mal ein installiertes Tool. Wenn dein Repository von Leuten angefasst wird, die kein PHP schreiben — SREs, Frontend-Menschen, dieser eine Go-Enthusiast — ist ein Makefile eine Lingua franca und Castor ein Dialekt. Das wische ich nicht weg. Aber Castor entschärft es mehr, als ich erwartet hätte: Der Installer ist ein Einzeiler per curl von castor.jolicode.com, und das --static-Flag liefert dir ein eigenständiges Binary mit eingebettetem PHP, sodass selbst ein nacktes CI-Image oder ein PHP-loser Laptop deine Tasks ausführen kann. Allgegenwart ist ein realer Preis, aber inzwischen ein einmaliger, kein wiederkehrender.
Es gibt auch eine Reifefrage, die man beim Namen nennen sollte. Einen Task-Runner zu adoptieren heißt zu wetten, dass er die Automatisierung deines Projekts überlebt, und Make hat vierzig Jahre Vorsprung. Warum ich für PHP-Teams trotzdem bei Castor lande: Das Risiko liegt eigentlich nicht bei Castor — es liegt bei Symfony. Das Tool ist größtenteils Klebstoff über Console, Process, Filesystem und Co., Komponenten mit riesiger Install-Basis und langen Support-Horizonten. Wenn Castor morgen verschwände, wäre deine castor.php schlichtes PHP, das gut dokumentierte Bibliotheken aufruft; die Migration ist ein Nachmittag, keine archäologische Grabung. Versuch das mal über ein 400-zeiliges Makefile mit .PHONY-Targets zu sagen, die Bash aufrufen, das Docker aufruft, das Bash aufruft.
Wenn du das Wasser testen willst, ohne alles umzuschreiben, fang da an, wo der Schmerz am kleinsten ist: bei deinen QA-Targets. Ein qa-Namespace mit phpunit-, csFixer- und phpstan-Tasks — jeder eine Zehn-Zeilen-Funktion, die per run() nach draußen ruft — plus ein qa:all-Task, der die anderen drei einfach als ganz normale PHP-Funktionen aufruft, mit benannten Argumenten wie csFixer(dryRun: true). Dieser letzte Teil ist das Killer-Feature, mit dem niemand wirbt: Task-Komposition ist Funktionskomposition. Keine Sub-Make-Aufrufe, keine Variablen-Weiterreich-Rituale, nur PHP, das PHP aufruft. Sobald dein Team das einmal gespürt hat, folgen die Docker-Targets von allein, und watch(), das Tasks bei Dateiänderungen neu ausführt, ersetzt die entr-Beschwörungsformel, die du bisher zwischen Projekten hin- und herkopiert hast.
Und hier will ich Widerspruch, denn ich weiß, dass diese Kolumne die Make-Loyalisten ärgern wird — und manche von euch haben Makefiles, die diese Loyalität wirklich verdienen. Wo verläuft deine Grenze? Gibt es eine Größen- oder Komplexitätsschwelle, unterhalb derer Makes Allgegenwart sprachnative Tasks schlägt, oder findest du, dass polyglotte Teams einen reinen PHP-Runner von vornherein disqualifizieren, egal wie gut er ist? Erzähl mir von dem Makefile, das du niemals hergeben würdest — oder von dem, das dich endgültig gebrochen hat.
Kommentare
Noch keine Kommentare — schreib den ersten.
Starte die Diskussion
Kein Konto, kein Passwort nötig — gib einfach deine E-Mail-Adresse ein, wir senden dir einen einmaligen Anmelde-Link. Beim ersten Mal bist du damit automatisch angemeldet.
Deine Bewertung wird nach der Anmeldung automatisch übernommen.
Schau in dein Postfach
Wir haben einen Anmelde-Link an … gesendet. Öffne ihn auf diesem Gerät — dieser Tab meldet dich automatisch an.
Nichts angekommen? Wirf einen Blick in den Spam-Ordner — und markiere die Mail dort als „Kein Spam“, dann landet sie künftig direkt im Postfach.