Contact salesFree trial
Blog

Erstellung von hybriden PHP-Go-CLIs mit der Symfony-Konsole

CLIGoPHPSymfony
Share

Wenn Sie die wichtigsten Erkenntnisse schnell durchlesen möchten, scrollen Sie bitte weiter, um unseren destillierten Bericht zu lesen. Wir haben ChatGPT verwendet, um die Grammatik und Syntax zu verbessern.

Einführung

Wenn man seit über einem Jahrzehnt eine entwicklerorientierte Plattform betreibt, neigt das Tooling dazu, sich mit der Zeit anzusammeln. Wir hatten eine Befehlszeilenschnittstelle (CLI), die vollständig in PHP implementiert war - angesichts unserer starken Verbindungen zum PHP- und Drupal-Ökosystem eine ganz natürliche Wahl zu diesem Zeitpunkt. Als sich jedoch unsere Zielgruppe und die unterstützten Sprachen vergrößerten, wurde uns klar, dass wir die Art und Weise, wie unsere CLI entwickelt und verteilt wurde, überdenken mussten.

  • Wir wollten eine einzige Binärdatei, die jeder installieren konnte - ohne zusätzliche Sprachabhängigkeiten.
  • Wir wollten den gesamten Befehlssatz (und die Benutzerfreundlichkeit) unserer alten PHP-basierten CLI beibehalten.
  • Wir wollten eine bessere Leistung und einfachere plattformübergreifende Unterstützung, was uns zu Go führte.

Und das Ergebnis? Eine hybride CLI, die unsere bestehende PHP-CLI-Logik in ein neues Go-basiertes Binary verpackt und mit der Symfony Console für konsistentes Befehlsrouting, Autovervollständigung und Shortcuts kombiniert. Im Folgenden erfahren Sie, wie wir zu diesem Ziel gekommen sind, warum wir bestimmte Entscheidungen getroffen haben und was wir auf unserem Weg gelernt haben.

Warum wir eine hybride CLI brauchten

Ursprünglich war unsere Befehlszeilenschnittstelle in PHP geschrieben, was für unsere damalige Hauptbenutzergruppe perfekt geeignet war. Als wir wuchsen, wuchsen auch die Tech-Stacks unserer Benutzer: Node.js, Python, Go, Ruby, Symfony und mehr. Wir mussten Teams, die PHP nicht installiert hatten, eine CLI-Erfahrung bieten - und sie wollten es auch nicht installieren, nur um ein Tool auszuführen.

Wichtige Ziele, die uns dazu brachten, unseren CLI-Ansatz zu überdenken:

  1. Abwärtskompatibilität. Wir konnten unsere bestehende PHP-CLI nicht einfach fallen lassen und die Arbeitsabläufe aller Beteiligten unterbrechen.
  2. Leistung ohne Abstriche bei der Funktionalität. Wir wollten eine schnellere Startzeit und einen robusten Funktionsumfang.
  3. Keine erzwungene PHP-Abhängigkeit mehr. Die Installation der CLI sollte auf jedem Betriebssystem und jeder Architektur "einfach funktionieren".

Die Wahl von Go für die neue CLI

Go ist im Ökosystem der Entwicklerwerkzeuge weit verbreitet (z. B. Docker, Terraform und unzählige andere Befehlszeilentools). Es lässt sich zu einer einzigen statischen Binärdatei kompilieren, die schnell ausgeführt werden kann und für Linux, macOS und Windows einfach zu verteilen ist. Dies waren unsere wichtigsten Beweggründe:

  1. Eine einzige Binärdatei. Keine zusätzlichen Abhängigkeiten, unkomplizierte Installation.
  2. Plattformübergreifende Kompilierung. Einmalige Kompilierung für jedes Ziel - keine komplizierten Build-Chains oder externe Tools erforderlich.
  3. Geschwindigkeit. Die Startzeit von Go und das Gleichzeitigkeitsmodell tragen dazu bei, dass sich die CLI schneller anfühlt.

Wie man PHP in Go ausführt (ja, wirklich)

Unser gesamter PHP-Code - tausende von Zeilen an Logik - muss den Benutzern weiterhin zur Verfügung stehen. Aber wie können wir diesen Code in einer Go-Binärdatei ausführen, ohne dass ein separates PHP auf dem Rechner des Benutzers erforderlich ist?

  1. Indem wir eine minimale PHP-Binärdatei einbetten. Wir haben eine abgespeckte Version von PHP entwickelt, die nur die Erweiterungen enthält, die unser CLI benötigt.
  2. Diese bündeln wir innerhalb der Go-Binärdatei. Wenn der Benutzer einen "legacy"-Befehl ausführt, ruft Go diesen eingebetteten PHP-Interpreter auf.
  3. Verteilen Sie "Legacy"- und "New"-Befehle. Handelt es sich um einen Legacy-Befehl, wird das eingebettete PHP gestartet. Wenn es sich um eine unserer neueren Funktionen handelt, bleiben Sie bei Go.

Durch diese Vorgehensweise mussten wir nicht alle bestehenden Befehle sofort umschreiben. Durch die Einbettung von PHP funktionierte alles weiter, aber wir konnten trotzdem neue Funktionen in Go hinzufügen, ohne die gesamte Veröffentlichung aufzuhalten.

Die Symfony-Konsole (in Go!)

In unserem ursprünglichen PHP-basierten CLI haben wir uns für Argumente, Shortcuts und Autovervollständigung auf die Symfony Console verlassen. Wir wollten diese vertraute Benutzererfahrung beibehalten - Abkürzungen wie p:init für project:init, oder gut strukturierte Hilfetexte, usw.

Es stellte sich heraus, dass die offizielle Symfony CLI in Go geschrieben ist und eine Go-basierte Symfony Console Komponente enthält. Indem wir unsere vorherige Go-Bibliothek (Cobra) mit dieser Symfony Console für Go austauschten, gewannen wir:

  • Konsistentes Kommando-Routing. Laden Sie alle Befehle, parsen Sie sie an der gleichen Stelle und entscheiden Sie dann, ob Go oder PHP sie verarbeiten soll.
  • Autovervollständigung. Die Symfony Console übernimmt die Erzeugung der Vervollständigung, so dass wir nur die vollständige Befehlsliste anzeigen müssen.
  • Vertraute Abkürzungen. Erzielen Sie die gleiche benutzerfreundliche Erfahrung, die wir in der PHP-CLI hatten.

Ausrollen der neuen CLI

  1. Die Legacy-CLI bleibt zunächst primär. Wir haben die PHP-CLI weiter gepflegt, um sicherzustellen, dass für bestehende Benutzer nichts kaputt geht.
  2. Neue Befehle debütieren in Go. Wir haben neue, spezialisierte Befehle (z. B. project:init, validate) in den neuen Go-Code aufgenommen.
  3. Inkrementelle Migration. Im Laufe der Zeit werden wir ältere PHP-Befehle in die Go-Codebasis verschieben. Die CLI ist dabei immer noch eine einzige Binärdatei.

Natürlich bedeutet die Pflege von zwei Codebasen (das eingebettete PHP für die alten Befehle und der neue Go-Code) zusätzliche Arbeit. Aber es gibt uns auch die Freiheit, in unserem eigenen Tempo zu arbeiten und sicherzustellen, dass jede Funktion gründlich getestet wird, ohne dass wir sie im großen Stil umschreiben müssen.

Testen, Testen, Testen

Wir wollten die Produktionsabläufe der Entwickler nicht unterbrechen:

  • Integrationstests stellen sicher, dass sich jeder Befehl in der neuen CLI genauso verhält wie in der alten (gleiche Eingabe, gleiche Ausgabe).
  • Unit-Tests für unsere Go-Befehle fangen alle Regressionen bei neuen Funktionen ab.
  • Mock-basierte End-to-End-Tests lassen Mock-Server laufen, um reale Abläufe vom ersten Aufruf bis zur endgültigen Ausgabe zu validieren.

Was steht als Nächstes an?

Wir migrieren nach und nach weitere Befehle auf Go, insbesondere solche, die eine Authentifizierung erfordern. Sobald dies abgeschlossen ist, können wir die Verwaltung von Anmeldeinformationen und Token in der neuen Binärdatei vollständig vereinheitlichen und möglicherweise die Handhabung von SSH-Schlüsseln und die Integration sicherer Speicher verbessern. Wir untersuchen auch Möglichkeiten, wie Entwickler von Drittanbietern die CLI erweitern können, da die Codebasis jetzt modularer ist.

Fazit

Eine ausgereifte Befehlszeilenschnittstelle neu zu schreiben ist selten einfach - vor allem dann nicht, wenn sich Tausende von Entwicklern bei ihren Produktionsabläufen täglich auf sie verlassen. Durch die Einführung einer hybriden Architektur konnten wir die vorhandenen PHP-basierten Funktionen beibehalten, die Verteilung drastisch verbessern (eine einzige Binärdatei, keine Sprachabhängigkeiten) und eine Grundlage für zukünftige Erweiterungen in Go schaffen.

Die wichtigsten Erkenntnisse:

  1. Hybride Ansätze können Ihnen Zeit verschaffen. Man muss nicht über Nacht Tausende von Zeilen Legacy-Code neu schreiben.
  2. Das Einbetten von Interpretern ist möglich. Wenn Sie ältere Sprachen oder Frameworks benötigen, kann der Versand kleiner, kuratierter Builds überraschend gut funktionieren.
  3. Testen ist das A und O. In einer hybriden Umgebung sind Integrations- und End-to-End-Tests entscheidend für die Vermeidung von Regressionen.

Wir hoffen, dass diese Reise Sie inspirieren kann, wenn Sie vor einem ähnlichen Dilemma zwischen Vergangenheit und Zukunft stehen. Ganz gleich, ob Sie neue Sprachen, neue Distributionsmodelle oder Möglichkeiten zur Vereinheitlichung Ihrer Entwicklererfahrung erforschen, eine hybride CLI könnte genau das sein, was Ihr Team braucht.

Ihr größtes Werk
steht vor der Tür

Kostenloser Test
Discord
© 2025 Platform.sh. All rights reserved.