隨著互聯網高速發展,我們日常生活中離不開各種各樣的應用和系統。這些應用和系統的開發離不開架構的設計,而目前較為流行的設計模式之一就是CQRS架構模式。
什么是CQRS?CQRS全稱是Command Query Responsibility Segregation,該架構模式將應用程序中的讀操作和寫操作分別表示為不同的模型。它通過將寫入和更新操作分離,使得應用程序能夠更加靈活地滿足不同的業務需求。
CQRS架構將應用程序分為兩個模型:命令模型和查詢模型。命令模型處理寫入操作,查詢模型則處理讀取操作。通過將兩個模型分開,我們可以實現更好的可擴展性和可維護性。
class CreateOrderCommandHandler
{
public function handle(CreateOrderCommand $command)
{
$order = new Order();
$order->create($command->getCustomerName(), $command->getProducts());
$this->orderRepository->save($order);
}
}
class OrderRepository
{
public function save(Order $order)
{
$this->entityManager->persist($order);
$this->entityManager->flush();
}
}
class OrderProjection
{
public function __invoke($event)
{
if ($event instanceof OrderCreated) {
$order = new OrdersView();
$order->setOrderId($event->getOrderId());
$order->setCustomerName($event->getCustomerName());
$order->setProductDetails($event->getProductDetails());
$this->entityManager->persist($order);
$this->entityManager->flush();
}
}
}
在CQRS中,寫入操作(commands)由命令模型負責處理,讀取操作(queries)由查詢模型處理。這兩個操作并行運行,不會相互干擾。下面我們針對這兩個模型做進一步介紹。
命令模型
命令模型在CQRS中扮演著非常重要的角色。它是用來處理寫入操作和數據持久化的。當一個寫入命令會改變應用程序的狀態時,執行這個命令的職責將被命令模型承擔。
命令模型中,我們通常會寫一個“寫操作處理程序”來處理命令,它會告訴應用程序如何處理我們所傳入的數據,并將它們保存到數據庫中。下面是一個例子,它描述了如何創建一個訂單:
class CreateOrderCommandHandler
{
public function handle(CreateOrderCommand $command)
{
$order = new Order();
$order->create($command->getCustomerName(), $command->getProducts());
$this->orderRepository->save($order);
}
}
class OrderRepository
{
public function save(Order $order)
{
$this->entityManager->persist($order);
$this->entityManager->flush();
}
}
上面的代碼中,CreateOrderCommandHandler類是一個命令模型,它具有處理創建訂單命令的方法(handle)。這個方法創建一個新的訂單實體,從我們的命令對象中獲取必要的數據,然后將訂單保存到數據庫中。
查詢模型
與命令模型不同,查詢模型用于處理讀取操作。查詢模型通常會使用一些“查找器”方法來獲取數據,并將這些數據以某種方式呈現給用戶。查詢模型并不會像命令模型那樣進行數據持久化。
class OrdersQueryHandler
{
public function handle()
{
$orders = $this->ordersRepository->getAllOrders();
$orderedProducts = $this->orderProductsRepository->getAll();
$ordersView = [];
foreach ($orders as $order) {
$products = [];
foreach ($orderedProducts as $product) {
if ($product->getOrderId() === $order->getId()) {
$products[] = $product->getProductDetails();
}
}
$ordersView[] = [
'id' =>$order->getId(),
'customerName' =>$order->getCustomerName(),
'products' =>$products
];
}
return $ordersView;
}
}
上述代碼中,OrdersQueryHandler類是一個查詢模型的例子。它具有一個處理所有訂單查詢的方法(handle)。這個方法會從我們的查詢倉儲中獲取所有的訂單,并使用相應的業務邏輯來處理這些訂單數據。
總之,CQRS架構模式使得我們可以更好地進行業務邏輯分離,使代碼更好維護和擴展,提高應用程序的可擴展性和可維護性。在PHP中,我們可以使用Symfony的Messenger組件來實現CQRS。Messenger提供了命令和查詢模型所需的所有特性,完全可以勝任。因此,Web應用程序的開發者們值得一試。