随着互联网高速发展,我们日常生活中离不开各种各样的应用和系统。这些应用和系统的开发离不开架构的设计,而目前较为流行的设计模式之一就是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应用程序的开发者们值得一试。