Hexagonale Architektur mit Symfony 8: Wann lohnt sie sich?

Hexagonale Architektur mit Symfony 8: Wann lohnt sie sich?

Dank PHP 8.4 und Symfony 8 wird die Umsetzung hexagonalen Designs endlich zum Standard, ohne gegen das Framework ankämpfen zu müssen. Erfahren Sie, wie neue Features wie Native Lazy Objects und Readonly-Klassen komplexe Business-Logik vereinfachen und wann sich der Wechsel von der klassischen CRUD-Struktur zur Domain-Driven Architecture für Ihr Projekt wirklich lohnt.

Dennis Schwenker-Sanders 8 Min. Lesezeit

Hexagonale Architektur mit Symfony 8: Wann lohnt sie sich?

Wer Symfony-Projekte für wachsende Unternehmen betreut, kennt das Gespräch. Irgendwann sagt jemand: "Wir sollten das nach Domain-Driven Design aufbauen." Manchmal hat er recht. Manchmal kostet es doppelt so viel und liefert dasselbe Ergebnis wie ein Standard-Setup. Den Unterschied zu kennen, ist keine akademische Frage, sondern eine handwerkliche.

Was Sie in 8 Minuten erfahren:

  1. Was Robin Chalas (Symfony Core Team) bei SymfonyOnline June 2026 unter "hexagonalem Denken mit Symfony 8" versteht und warum es jetzt anders ist als früher
  2. Welche Symfony-8-Features sich natürlich an DDD-Patterns anschmiegen und welche konkreten Muster das sind
  3. Wann hexagonale Architektur für Ihr Projekt sinnvoll ist und wann ein Standard-Symfony-Setup die bessere Entscheidung bleibt

Robin Chalas, Symfony Core Team Member und CEO von baksla.sh, hat seinen Talk "Symfony 8: The Hexagonal Track" sowohl beim SymfonyDay Montreal als auch beim SymfonyOnline June 2026 (11.-12. Juni) gezeigt. Die Kernthese: Strukturierung einer Applikation rund um die Domäne statt rund um das Framework fühlte sich früher an wie "swimming against the current". Das ändert sich jetzt, dank PHP 8.4-Features und Symfony-8-Entwicklungen, die sich "natürlich an hexagonales Denken und taktische DDD-Patterns anschmiegen, ohne Workarounds, ohne Ringen mit den Werkzeugen".

Was macht das konkret aus? Und: Lohnt es sich für Ihr Projekt?

Was hat sich mit Symfony 8 konkret verändert?


Früher (Symfony 4-6)

Jetzt (Symfony 8 + PHP 8.4)

Entities mit öffentlichen Settern für Doctrine

Readonly Properties + Private Constructor = Aggregate-Roots ohne Kompromisse

Service-Klassen als Gott-Objekte

Attribute-basierte DI + Console Argument Resolvers = schlanke Use-Cases

Event-Handling über Doctrine Lifecycle Callbacks

Domain Events als First-Class Citizens im Messenger

Repository als Doctrine-Wrapper

Interface-basierte Ports, Symfony DI injiziert den Adapter

Value Objects: Boilerplate oder externe Libraries

Backed Enums + Readonly Classes = Value Objects nativ

Der entscheidende Schritt: PHP 8.4 bringt Native Lazy Objects, was bedeutet, dass Doctrine-Entities jetzt echte Readonly-Aggregate sein können, ohne Performance-Kompromisse beim Lazy-Loading. Das war früher der häufigste Bruchpunkt zwischen DDD-Purismus und Doctrine-Pragmatismus.

Betrifft Sie das? Schnelltest in 30 Sekunden

Jetzt relevant wenn: Ihre Symfony-App wächst über ein CRUD-System hinaus. Wenn Ihr Team beginnt, Begriffe wie "das System muss den Bestand reservieren, bevor die Zahlung ausgelöst wird" zu diskutieren, haben Sie Domänen-Komplexität, die Architektur braucht.

Auf dem Radar behalten wenn: Ihr Projekt auf Symfony 7.4 LTS läuft und DDD kein akutes Thema ist. Die Features funktionieren erst vollständig ab Symfony 8 mit PHP 8.4.

Kein Thema wenn: Ihr Projekt primär CRUD ist: Produkte anlegen, anzeigen, bearbeiten, löschen. Standard-Symfony-Setup ist hier die richtige Entscheidung. Hexagonale Architektur für ein Webshop-Backend ohne komplexe Domänen-Logik ist Overengineering.

Kommt Ihnen das bekannt vor?

Wachsende Domänen-Komplexität, aber unsicher ob hexagonale Architektur die richtige Antwort ist. Ich helfe Ihnen, das für Ihr konkretes Projekt einzuschätzen.

  • Symfony-Projekte mit wachsender Komplexität
  • Einschätzung ohne Dogmatismus
Kostenlosen Check anfragen →

⏱️ Antwort binnen 24 Stunden

Was steckt hinter "hexagonalem Denken"?

Hexagonale Architektur (auch Ports & Adapters) ist eine Idee aus den 2000er Jahren: Die Geschäftslogik (Domain) steht im Mittelpunkt. Alles andere (Datenbank, HTTP, CLI, externe APIs) wird über Ports (Interfaces) angebunden. Adapters implementieren diese Interfaces.

Das klingt abstrakt. Konkret bedeutet es: Ihr Bestellprozess-Code weiß nicht, ob die Daten in MySQL, PostgreSQL oder einem In-Memory-Repository gespeichert werden. Er arbeitet nur mit dem OrderRepositoryInterface. Wer ihn implementiert, entscheidet Symfony über DI.

// Port: das Interface in der Domäne
namespace App\Domain\Order;

interface OrderRepositoryInterface
{
public function findById(OrderId $id): Order;
public function save(Order $order): void;
}

// Adapter: die Doctrine-Implementierung in der Infrastruktur-Schicht
namespace App\Infrastructure\Persistence;

class DoctrineOrderRepository implements OrderRepositoryInterface
{
public function __construct(private EntityManagerInterface $em) {}

public function findById(OrderId $id): Order {
return $this->em->find(Order::class, $id->value());
}
}

// Symfony DI verbindet Port und Adapter:
# config/services.yaml
App\Domain\Order\OrderRepositoryInterface: '@App\Infrastructure\Persistence\DoctrineOrderRepository'

Was früher Boilerplate war, ist jetzt sauber: Symfony 8 verbindet Port und Adapter über reguläres Autowiring. Keine Custom-Compiler-Passes, keine manuelle Factory.

Welche taktischen DDD-Patterns profitieren am meisten?

Aggregate Roots mit Readonly Classes: Ein Order-Aggregate als Readonly Class erzwingt, dass der Zustand nur über Domain-Methoden verändert wird. Keine fremde Methode kann einfach $order->status = 'shipped' schreiben. Das war früher mit Doctrine-Entities schwierig, weil Doctrine mutable Objekte bevorzugt. PHP 8.4 Native Lazy Objects lösen das.

Domain Events über Messenger: Wenn ein Bestellstatus sich ändert, emittiert das Aggregate einen OrderShippedEvent. Symfony Messenger verteilt ihn an alle Handler (Email-Versand, Lager-Update, Analytics). Die Domäne kennt die Handler nicht, die Handler kennen sich nicht gegenseitig.

Value Objects als Backed Enums: OrderStatus war früher eine Klasse mit Konstanten und Validierung. Jetzt ist es ein Backed Enum: typsicher, in Doctrine direkt verwendbar, keine zusätzliche Library.

// Value Object als Backed Enum (PHP 8.1+, nativ in Symfony 8)
enum OrderStatus: string
{
case Pending = 'pending';
case Paid = 'paid';
case Shipped = 'shipped';
case Cancelled = 'cancelled';

public function canTransitionTo(self $new): bool
{
return match($this) {
self::Pending => in_array($new, [self::Paid, self::Cancelled]),
self::Paid => $new === self::Shipped,
default => false,
};
}
}
// Domänen-Logik (Transitionen) sitzt im Enum, nicht im Service.
KurzBacked Enums für Status-Transitions, Readonly Classes für Aggregate, Domain Events über Messenger: Das sind die drei Patterns, die in Symfony 8 sofort ohne Overengineering funktionieren.

⚡ Architektur-Review für Ihr Symfony-Projekt?

Ich prüfe, welche taktischen DDD-Patterns in Ihrer bestehenden Codebasis sinnvoll wären und was der Aufwand realistisch ist.

  • Symfony-Projekte seit über 10 Jahren
  • Pragmatischer Ansatz, kein Purismus
Architektur besprechen →

⏱️ Antwort binnen 24 Stunden

📞 Oder direkt anrufen: 04481 - 9099658

Wann lohnt sich hexagonale Architektur wirklich?

Hier ist die Frage, die in Konferenz-Talks oft ausgespart wird. Ein Kommentar unter dem SymfonyDay-Montreal-Blogpost formuliert es direkt: "From 2022 to 2025, I worked on a Symfony project where the lead developer chose DDD simply because he liked it. We spent more than double the budget and delivered the same result a standard Symfony setup would have produced."

Das ist kein Einzelfall. Aus meiner Erfahrung mit Symfony-Projekten in der deutschen Agentur-Landschaft sehe ich das Muster regelmäßig: DDD wird eingesetzt, weil es architektonisch interessant ist, nicht weil die Domänen-Komplexität es erfordert.

DDD ist kein Qualitätsmerkmal, es ist ein Werkzeug für ein bestimmtes Problem. Das Problem ist: Wachsende, sich verändernde Geschäftslogik, die von mehreren Teams gepflegt wird und deren Regeln aus der Fachdomäne stammen, nicht aus der Technik. Wenn Ihr Projekt dieses Problem nicht hat, ist DDD Overengineering.

Wann ist hexagonale Architektur die richtige Wahl?

Geeignet wenn: Die Domänen-Logik wächst und die Regeln kommen aus dem Business ("Bestellungen unter 50€ können nicht rückerstattet werden, wenn sie älter als 14 Tage sind, außer bei Qualitätsmängeln"). Wenn das Team wächst und verschiedene Teams verschiedene Bounded Contexts ownen. Wenn die Infrastruktur sich ändern kann (Datenbank-Migration, Cloud-Provider-Wechsel) ohne die Domäne anzufassen.

Nicht geeignet wenn: Der Hauptanwendungsfall ist CRUD. Wenn das Team klein ist (2-3 Entwickler) und die Domäne stabil. Wenn die Deliverable-Geschwindigkeit wichtiger ist als langfristige Wartbarkeit. Wenn das Team keine DDD-Erfahrung hat und das Projekt die Lernkurve nicht tragen kann.

Der pragmatische Mittelweg: Taktische DDD-Elemente ohne den vollen hexagonalen Stack. Backed Enums für Status-Transitions. Value Objects für Identifier. Domain Events für Side-Effects. Repository-Interfaces für testbare Use-Cases. Das sind keine Architektur-Entscheidungen, die Wochen Overhead kosten. Das sind Code-Qualitäts-Entscheidungen, die sich sofort amortisieren.

KurzHexagonale Architektur lohnt sich für wachsende Domänen mit komplexen Regeln. Für CRUD-Projekte ist Standard-Symfony die bessere Wahl. Taktische DDD-Elemente (Enums, Value Objects, Domain Events) lohnen sich fast immer.

Aus der Praxis: Was ich bei Bestandssystemen sehe

Aus der Praxis

Was mir bei Code-Reviews und Einarbeitungen in Bestandssysteme häufig begegnet: Zwei Extreme. Entweder alle Geschäftslogik in Controllern ("das ist doch Symfony, da gehört es hin"), was nach zwei Jahren zu unwartbaren Controllern mit 500 Zeilen führt. Oder ein vollständig hexagonales Setup, das vor drei Jahren mit Begeisterung aufgesetzt wurde und jetzt niemand mehr vollständig versteht. Der produktive Bereich liegt dazwischen: Geschäftslogik in Services und Entities, klare Trennung von Infrastruktur und Domain, ohne den Full-DDD-Overhead. Als Symfony-Entwickler, der regelmäßig in Bestandssysteme einarbeitet, ist diese Balance der häufigste Beratungspunkt.

Robin Chalas trägt dabei seine "zwei Hüte" bewusst: Core-Team-Mitglied und DDD-Praktiker. Das ist genau die Kombination, die den Talk interessant macht. Wer will, kann sich die Aufzeichnung von SymfonyOnline June 2026 auf dem offiziellen Symfony-YouTube-Kanal anschauen.

Zusammenfassung

Symfony 8 + PHP 8.4 macht hexagonale Architektur und taktische DDD-Patterns ohne Workarounds möglich. Readonly Classes, Native Lazy Objects, Backed Enums und Symfony DI arbeiten zusammen.

Die drei sofort nützlichen Patterns: Backed Enums für Status-Transitions, Value Objects als Readonly Classes, Domain Events über Symfony Messenger.

Der ehrliche Vorbehalt: Hexagonale Architektur für CRUD-Projekte ist Overengineering. Den DDD-Kommentar aus dem Symfony-Blog-Kommentar ("doppeltes Budget, gleiches Ergebnis") sollte jeder im Kopf haben, bevor er DDD für ein Projekt vorschlägt.

Der pragmatische Mittelweg: Taktische DDD-Elemente ohne den vollen Stack. Das amortisiert sich schnell und erzeugt keinen Overhead.

Sie wissen, ob Ihr Projekt Domänen-Komplexität hat.

Wenn ja, lassen Sie uns klären, welche Patterns konkret helfen und was das realistisch kostet. Kein Dogmatismus, kein Over-Engineering.

  • Symfony-Architektur seit über 10 Jahren
  • Pragmatische DDD-Integration ohne Purismus
  • Für Agenturen und KMU-Projekte
Nächsten Schritt klären →

Häufige Fragen

Was ist der Unterschied zwischen hexagonaler Architektur und DDD?

Domain-Driven Design (DDD) ist ein Ansatz, Softwarestruktur an der Fachdomäne auszurichten. Hexagonale Architektur (Ports & Adapters) ist ein Muster, das die Domäne von Infrastruktur entkoppelt. Beides ergänzt sich: DDD liefert die Konzepte (Aggregate, Value Objects, Domain Events), hexagonale Architektur die Schichtung (Domain-Kern ist isoliert, Infrastruktur wird über Interfaces angebunden). Man kann DDD ohne hexagonale Architektur umsetzen und umgekehrt.

Funktioniert hexagonale Architektur mit Symfony LTS 7.4?

Grundsätzlich ja, aber ohne die vollen Vorteile. PHP 8.4 Native Lazy Objects (die Doctrine-Readonly-Entities ohne Performance-Kompromisse ermöglichen) setzen PHP 8.4 voraus. Backed Enums sind seit PHP 8.1 verfügbar und funktionieren auf 7.4. Console Argument Resolvers und neue DI-Features sind Symfony-8-spezifisch. Für Symfony 7.4 ist taktisches DDD möglich, der "Schwimmen mit dem Strom"-Effekt zeigt sich erst vollständig auf 8.x.

Was sind taktische DDD-Patterns und wie unterscheiden sie sich von strategischem DDD?

Strategisches DDD (Bounded Contexts, Context Maps, Ubiquitous Language) befasst sich mit dem großen Bild: Wie teilen wir eine komplexe Domäne in abgegrenzte Bereiche auf? Taktische DDD-Patterns (Aggregate, Value Objects, Domain Events, Repositories) sind die konkreten Code-Bausteine. Für die meisten Agentur-Projekte sind die taktischen Patterns der relevante Einstieg. Strategisches DDD lohnt sich erst bei mehreren Teams und sehr komplexen Domänen.

Wie lange dauert es, hexagonale Architektur in ein bestehendes Symfony-Projekt einzuführen?

Das hängt vom Ausgangszustand und dem Umfang ab. Taktische DDD-Elemente (Backed Enums, Value Objects, einfache Domain Events) können in einzelnen Features parallel eingeführt werden, ohne die bestehende Codebasis umzuschreiben. Eine vollständige hexagonale Umstrukturierung eines mittleren Symfony-Projekts (10+ Entities, komplexe Geschäftslogik) ist ein mehrtägiges bis mehrwöchiges Vorhaben, das Staging und schrittweise Migration erfordert.

Kann man hexagonale Architektur mit Shopware kombinieren?

Ja, aber mit Einschränkungen. Shopware 6 hat eigene Architekturkonventionen (Decorator-Pattern, DataAbstractionLayer). Custom Business-Logik, die außerhalb des DAL läuft (z.B. komplexe Pricing-Rules, B2B-Bestellprozesse), kann in hexagonale Services ausgelagert werden. Der Shopware-Core selbst folgt nicht dem hexagonalen Muster. Für Shop-Custom-Logik ist es eine sinnvolle Ergänzung, für Core-Anpassungen eher nicht.

Artikel teilen: