Tobias
05.09.2017 von Tobias

Die Sylius Architektur - Components, Bundles & State Machine

Seit unserem letzen Bericht über Sylius hat sich einiges getan im Hause der polnischen Softwareschmiede. Am 13. September soll die langersehnte erste Stable-Version des E-Commerce Frameworks erscheinen. Es könnte also kaum einen besseren Zeitpunkt für den bevorstehenden Hackaton vom 13. - 15. Oktober bei solutionDrive GmbH in Nürnberg geben.

Bis es soweit ist, wollen wir in einem weiteren Artikel auf drei grundlegende Aspekte der Architektur von Sylius eingehen: Components, Bundles und State Machines. Die folgende Grafik zeigt schematisch das Zusammenspiel zwischen Components und Bundles:

Architektur Überblick

Components

Das Fundament für das Framework bilden Components. Das sind voneinander losgelöste, zweckgebundene Code-Einheiten, die selbst nicht auf einem Framework basieren. Sie sind vergleichbar mit klassischen PHP-Bibliotheken. Durch die abstrakte Implementierung können sie theoretisch auch in anderen Frameworks, wie etwa Laravel via composer Verwendung finden.

In den Components sind die grundlegenden Ressourcen definiert, die gebraucht werden, um komplexe e-Commerce-Logik abzubilden. Dazu gehören hier neben Basis-Models und Repositories für Ressourcen auch Factory-Klassen, welche für die Erzeugung von Ressourcen verantwortlich sind. Das ist ein grundlegender Vorgang, der in Sylius konsequent implementiert ist. Wollt Ihr also ein neues Produkt erzeugen, so könntet Ihr dies mit folgendem Code erreichen:

$factory = new Factory(Product::class);

$product = $factory->createNew();

Dieser Vorgang entspricht dem SOLID-Prinzip und hat einige Vorteile. Zum einem ist der Code einfach testbar, da Ihr die Factory mit wenig Aufwand mocken könnt. Zum anderen könnt Ihr leicht Anpassungen bei der Erzeugung der Ressource vornehmen oder die vorhandene Logik vollständig durch eine eigene Implementierung ersetzen.

Bundles

Bundles sind im Gegensatz zu Components ein Symfony-spezifisches Konzept. Ein Bundle entspricht im klassischen E-Commerce-Kontext etwa einem Modul oder Plug-in. Es handelt sich dabei um mehrere Dateien innerhalb eines Verzeichnisses, die ein bestimmtes Feature implementieren. Zu diesen Dateien können neben PHP-Dateien auch Templates, Stylesheets, JavaScript Files sowie Tests gehören.

Sylius liefert von Haus aus eine Anzahl brauchbarer Bundles mit, wie beispielsweise API/Admin/Shop-Bundle. Viele davon sind, ähnlich wie die Components, voneinander entkoppelt. So ist es problemlos möglich, das Shop-Bundle zu deaktivieren und stattdessen innerhalb einer IOS- oder Android-App vollständig über die API zu kommunizieren. Dabei können von „In den Warenkorb legen“ bis „Checkout“ die gleichen Operationen mit derselben Business-Logik durchgeführt werden, wie üblicherweise mit der Shop-GUI. In diesem Fall wäre das Shop-Bundle überflüssig und sollte aus dem App-Kernel entfernt werden, um das Projekt nicht unnötig aufzublähen. Ebenfalls möglich wäre es, mit entsprechenden Anpassungen, Sylius nicht nur für Business2Customer sondern auch für Business2Business Projekte zu verwenden.

Grundlage für das Sylius-Ökosystem

Die Entkoppelung ist auf Bundle-Ebene nur bis zu einem bestimmten Punkt realisiert, der höchstwahrscheinlich für die meisten e-Commerce Anwendungen ausreichend ist. Innerhalb des Core-Bundles sind eine Vielzahl von Standard-Bundles mit Components verknüpft. Sie bilden die Grundlage für das Sylius-Ökosystem. Bei umfassenderen Modifikationen an der Basis-Logik kann das Core-Bundle jedoch durch eine Eigenimplementierung ersetzt werden.

Sollen lediglich Anpassungen an bestehenden Entitäten vorgenommen werden, muss jedoch keine Änderung im entsprechenden Bundle oder gar im Core-Bundle vorgenommen werden. Sylius bietet hier einen intuitiven Ansatz, der nicht viel neuen Code erfordert. In vielen Fällen würdet Ihr mehr Konfigurieren als Programmieren.

Falls Ihr zum Beispiel die Order-Entity um ein Attribut wie Export-Status erweitern wollt, sind folgende drei Schritte notwendig: 

  • Innerhalb eines Bundles erstellt Ihr im Ordner Entity eine Klasse mit dem Namen „OrderEntity“. Diese Klasse erweitert mit Hilfe von extend die Basis-Klasse Sylius\Component\Core\Model\Order.
  • Da das neue Feld auch in der Datenbank gespeichert werden soll, müsst Ihr das EntityMapping via Resources/config/doctrine/Order.orm.yml erweitern. Hier erfasst Ihr lediglich das Mapping für das neu angelegte Attribut, also Spaltenname, Typ etc.
  • In einer config.yml (üblicherweise unter Resource/config/app) teilt Ihr Sylius mit, dass es nun die neu erstellte Klasse als Order-Klasse verwenden soll.

Nach einer Aktualisierung der Datenbank via Konsole könnt Ihr bereits mit dem neuen Attribut arbeiten. Die entsprechenden Werte könnten zum Beispiel nach wenigen weiteren Anpassungen in Listen oder Detailansichten angezeigt werden.

State Machines

Vor allem im E-Commerce müssen Prozesse, wie etwa der „Checkout“, oftmals individuell auf die Bedürfnisse von Kunden abgestimmt werden. Bei vorhandenen Lösungen, wie OXID oder Shopware, ist dieser Vorgang teilweise mit viel Aufwand verbunden. Sylius setzt dagegen auf State Machines. Jede State Machine hat für eine Entity eine Anzahl definierter Status. Dabei ist auch festgelegt, welche Statuswechsel erlaubt sind und welcher Service zuvor ausgeführt werden muss. Die Konfiguration erfolgt dabei komplett über yml Dateien. Das Diagramm unten zeigt ein Beispiel dafür, wie die Konfiguration für den Checkout-Prozess aussehen kann:

Fazit

Alles in allem bietet Sylius eine interessante und durchdachte Architektur. Mitte Oktober wollen wir bei uns im schönen Nürnberg zur Tat schreiten und gemeinsam neue Features entwickeln. Wir freuen uns darauf, mit Euch über Eure Erfahrungen und die Vor- und Nachteile von Sylius zu diskutieren.