Warum gewöhnliches CRUD bei wachsendem Projekt nicht mehr funktioniert
\n\nStellen Sie sich vor: Sie schreiben einen Online-Shop in PHP. Zuerst ist alles einfach – Produkt hinzugefügt, Preis geändert, gelöscht. Aber nach einem halben Jahr kommen neue Anforderungen hinzu: Audit aller Änderungen, Wiederherstellung von Daten zu einem bestimmten Datum, komplexe Rabattlogik. Gewöhnliches CRUD (Create, Read, Update, Delete) beginnt zu bröckeln. Die Datenbank wird zum Chaos, und jede neue Kundenanfrage erfordert das Umschreiben der Hälfte des Systems.
\n\nKommt Ihnen das bekannt vor? Dann werden Ihnen CQRS (Command Query Responsibility Segregation) und Event Sourcing sicher nützlich sein – zwei leistungsstarke Muster, die den Ansatz zur Entwicklung verändern. In diesem Artikel analysieren wir sie anhand realer PHP-Beispiele, damit Sie sie in Ihren Projekten anwenden können.
\n\nWas sind CQRS und Event Sourcing in einfachen Worten
\n\nCQRS: Trennung von Befehlen und Abfragen
\n\nCQRS ist ein Architekturmuster, das Operationen in zwei Typen unterteilt: Befehle (ändern den Zustand) und Abfragen (lesen den Zustand). Im klassischen MVC arbeiten sowohl der Controller als auch das Modell mit denselben Entitäten. CQRS schlägt vor, diese Verantwortlichkeiten zu trennen.
\n\nStellen Sie sich eine Bibliothek vor: Es gibt einen separaten Tisch zum Ausleihen von Büchern (Befehle) und einen separaten Tisch zum Lesen (Abfragen). Niemand stört den anderen, und jeder ist für seine Aufgabe optimiert.
\n\nEvent Sourcing: Änderungsverlauf statt aktuellem Zustand
\n\nEvent Sourcing ist eine Methode der Datenspeicherung, bei der Sie nicht den aktuellen Zustand eines Objekts speichern, sondern die Abfolge aller Ereignisse, die zu diesem Zustand geführt haben. Anstelle einer einzelnen Zeile "Bestellung Nr. 123: Status = geliefert" speichern Sie: "Bestellung erstellt → Bezahlt → Versandt → Geliefert".
\n\nDas ist wie eine Videoaufnahme anstelle eines Fotos: Sie können jederzeit zurückspulen und sehen, was zu einem bestimmten Zeitpunkt passiert ist.
\n\nWann sollte man CQRS und Event Sourcing in PHP einsetzen
\n\nDiese Muster sind keine silberne Kugel. Für einen einfachen Blog sind sie überdimensioniert. Aber hier sind Szenarien, in denen sie unverzichtbar sind:
\n\n- \n
- Komplexe Domänenlogik (Finanzen, Buchung, Logistik) \n
- Audit-Anforderungen – Sie müssen wissen, wer wann Daten geändert hat \n
- Wiederherstellung des Zustands zu einem beliebigen Datum \n
- Mikroservice-Architektur – Ereignisse lassen sich leicht zwischen Diensten übertragen \n
- Hohe Leselast – Sie können ein separates, für Abfragen optimiertes Read-Modell erstellen \n
Wenn Ihr Projekt ein Online-Shop mit Tausenden von Bestellungen, ein CRM-System oder eine Bankanwendung ist – dann werden Ihnen CQRS und Event Sourcing sicher nützlich sein.
\n\nPraktische Implementierung von CQRS in PHP
\n\nKommen wir zum Code. Wir implementieren ein einfaches Bestellverwaltungssystem. Beginnen wir mit CQRS.
\n\nSchritt 1: Befehle und Abfragen definieren
\n\nEin Befehl ist ein DTO (Data Transfer Object), das alle Daten zur Ausführung einer Operation enthält. Ein Befehl gibt niemals Daten zurück – er ändert nur den Zustand.
\n\n<?php\n// src/Application/Command/CreateOrderCommand.php\nnamespace App\\Application\\Command;\n\nclass CreateOrderCommand\n{\n public function __construct(\n public readonly string $orderId,\n public readonly string $customerId,\n public readonly array $items, // [['productId' => '...', 'quantity' => 2], ...]\n public readonly \\DateTimeImmutable $createdAt\n ) {}\n}\n\n\nEine Abfrage ist ebenfalls ein DTO, jedoch zum Lesen. Sie kann Filter enthalten und Daten zurückgeben.
\n\n<?php\n// src/Application/Query/GetOrderQuery.php\nnamespace App\\Application\\Query;\n\nclass GetOrderQuery\n{\n public function __construct(\n public readonly string $orderId\n ) {}\n}\n\n\nSchritt 2: Befehlshandler erstellen
\n\nEin Befehlshandler ist ein Dienst, der die Geschäftslogik ausführt. Er nimmt einen Befehl entgegen und ändert den Zustand