Hallo zusammen,
In diesem Artikel zeige ich euch anhand praktischer Beispiele, wie unerwartete Probleme in Magento 2 & Adobe Commerce-Projekten entstehen können — beim Erstellen und Verwenden eigener CLI-Befehle oder solcher von Drittanbietern. Das wird besonders dann relevant, wenn ihr mit CI/CD-Pipelines arbeitet und dort Projekt-Setups sowie Tests ausführt.
Der Hauptdarsteller unseres Artikels: ISSUE: magento setup command is throwing magento.flag does't exist. Wir schauen uns dieses Problem genauer an, verstehen seine Ursachen und finden Wege, es zu beheben.
Hinweis: Kurze Anmerkung zur Benennung — dieser Artikel behandelt sowohl Adobe Commerce als auch Magento 2. Denn Adobe Commerce ist Magento. Long Live Magento!
Bei der Arbeit an verschiedenen Magento 2-Projekten bin ich immer wieder auf Probleme gestoßen, wenn ich ein `clean` Setup mit einer frisch erstellten Datenbank durchgeführt habe. Das passiert meist beim Aufsetzen von Integrations- oder Funktionstests in Pipelines & lokalen Umgebungen — aber auch bei Upgrades, Migrationen oder Deployments kann dieses Problem auftauchen.
Die Übeltäter? Hier sind zwei lästige Fehlermeldungen, die dir vielleicht bekannt vorkommen:
The default website isn't defined. Set the website and try again.
Bei Commerce-Editionen kommt außerdem noch diese hinzu:
SQLSTATE[42S02]: Base table or view not found: 1146 Table
'magento2.flag' doesn't exist, query was:
SELECT flag.* FROM flag WHERE (flag.flag_code='staging')
Wenn du diese Fehler während der Ausführung von `php bin/magento setup:install` siehst, geben sie wenig Aufschluss über das eigentliche Problem. Nach einigen frustrierenden Recherche-Stunden wirst du herausfinden, dass diese Fehler durch den vorzeitigen Zugriff auf die DB-Ressource entstehen — was die Initialisierung von Konfigurations- und Status-Entitäten aus der Magento-DB auslöst.
Das Dilemma: Du kannst zum jetzigen Zeitpunkt keine Daten aus der DB abrufen, weil die Tabellen noch gar nicht existieren. Sie werden erst während des Installationsprozesses erstellt und befüllt — nicht vorher. ¯\_(ツ)_/¯
Wir stecken also in einem zirkulären Problem: Wir wollen das System installieren, werden aber daran gehindert, weil es noch nicht installiert ist. Verwirrend, oder?🤪
Das passiert, weil irgendwo jemand verfrüht auf die DB-Verbindung zugreift. Klingt offensichtlich — und ich hoffe, du bist so dankbar für diese Erkenntnis wie Sam Eliot.
Dieser "Jemand" steckt in `bin/magento` und wird aufgerufen, bevor der eigentliche Befehl ausgeführt wird. Meistens sind die Konstruktoren der CLI-Befehle schuld. Ich erkläre dir warum.
Schau dir zur Verdeutlichung diesen Code an:
class DoSmthing
{
private ?string $dummyConfigValue;
public function __construct(ScopeConfigInterface $storeManager)
{
$this->dummyConfigValue = $storeManager->getValue('some/dummy/path', ScopeInterface::SCOPE_STORE);
}
public function getValue(): ?string
{
return $this->dummyConfigValue;
}
}
class DummyCommand extends Command
{
// ...
public function __construct(DoSmthing $model, string $name = null)
{
$this->model = $model;
parent::__construct($name);
}
// ...
}
Die Wurzel des Problems liegt in den Konstruktoren beider Klassen.
In der Klasse DoSmthing wird versucht, einen Konfigurationswert abzurufen. Dieser Aufruf greift auf die Tabellen store, store_website und core_config_data zu — und zwar bereits beim Erstellen des DummyCommand-Objekts.
Und was passiert, wenn dieser Code läuft, bevor die Tabellen bereit sind? Genau — Fehler!
Merke dir diese goldene Regel: Jede CLI-Command-Klasse wird initialisiert, sobald du php bin/magento aufrufst. So sparst du dir künftige Kopfschmerzen:
Das Problem aus unserem Beispiel mit DummyCommand lässt sich lösen, indem du folgende Zeilen zur di.xml hinzufügst:
<type name="AbcTest\DummyConsoleCommand\Console\Command\DummyCommand">
<arguments>
<argument name="model" xsi:type="object">
\AbcTest\DummyConsoleCommand\Model\DoSmthing\Proxy
</argument>
</arguments>
</type>
Proxy ist ein bekanntes Pattern und wird in Magento häufig eingesetzt, um unnötige Code-Ausführungen zu vermeiden, bis wir die Ressource wirklich benötigen. In unserem Beispiel wird das DoSmthing-Objekt erst dann instanziiert, wenn eine Methode dieser Klasse aufgerufen wird.
Kein Konfigurationsabruf beim Erstellen des CLI-Objekts — kein Fehler.
Mehr Details zum Proxy-Pattern findest du hier: Proxies.
Bei Projekten mit wenigen Extensions ist es nicht besonders schwierig, die problematischen CLI-Befehle ausfindig zu machen. Bei umfangreicheren Legacy-Projekten oder solchen mit vielen Drittanbieter-Extensions wird die Suche jedoch schnell zur Tortur.
Um Zeit zu sparen, haben wir eine Lösung entwickelt, die die Proxy-Injection automatisiert. Wir stellen vor: run-as-root/magento-cli-auto-proxy.
Dieses Package injiziert Proxy in alle __construct-Argumente von CLI-Befehlen, die für Proxying geeignet sind. Das Ergebnis: Keine Fehler mehr durch verfrühten Ressourcenzugriff — und als angenehmer Nebeneffekt eine schnellere Ausführung von php bin/magento und php bin/magento setup:install.
Schau dir die README für weitere Details an. Wir freuen uns über Feedback und Beiträge!
Kurz zusammengefasst:
Danke, dass du dir die Zeit genommen hast, diesen Artikel zu lesen. Ich freue mich über deine Fragen und Feedback.
Happy coding und... Long Live Magento! 😁
Sprich mit Vlad, unserem Adobe Commerce-Experten, und verbessere deinen Entwicklungs-Workflow.