remotelyliving / php-command-bus

PHP 查询总线,用于抽象查询、数据加载和图构建

1.0.0 2020-05-26 22:35 UTC

This package is auto-updated.

Last update: 2024-09-19 22:26:24 UTC


README

Build Status Total Downloads Coverage Status License Scrutinizer Code Quality

php-command-bus: 🚍 PHP 的命令总线实现 🚍

用例

如果您需要一个轻量级的查询总线作为 CQRS 的补充,这个库可能对您有所帮助。

安装

composer require remotelyliving/php-command-bus

用法

创建命令解析器

解析器可以手动添加处理程序或在其 PSR-11 服务容器中定位它们。命令与处理程序一一对应,并通过命令类名作为查找键进行映射。

$resolver = Resolver::create($serviceContainer) // can locate in service container
    ->pushHandler(Commands\ReserveRoom::class, new Handlers\ReserveRoom()) // can locate in a local map {command => handler}
    ->pushHandlerDeferred(Commands\Checkout::class, fn() => new Handlers\Checkout()); // can locate deferred to save un unnecessary object instantiation

创建命令总线

命令总线接受命令解析器、可选的 PSR-14 事件调度器和您想要的任何中间件并将其推送到堆栈上。

$resolver = Resolver::create($container);
$commandBus = CommandBus::create($resolver, $psr14EventDispatcher | null)
    ->pushMiddleware($myMiddleware1);

$command = new Commands\ReserveRoom(123);
$commandBus->handle($command);

中间件是任何可调用函数。该库包含一些基本中间件:src/Middleware

这就是全部了!

命令

这个库的命令故意未实现。它只是一个对象。对于命令对象,我的建议是将其保持为您需要执行命令的数据传输对象(DTO)。

一个示例命令可能如下所示

class ReserveRoom
{
    private User $user;

    private Room $room;

    public function __construct(User $user, Room $room)
    {
        $this->user = $user;
        $this->room = $room;
    }

    public function getUser(): User
    {
        return $this->user;
    }

    public function getRoom(): Room
    {
        return $this->room;
    }
}

如您所见,它只是几个获取器

处理程序

处理程序是发生魔法的地方。

  • 在构造函数中注入您需要的任何领域服务以执行命令。
  • 执行命令的逻辑。
  • 产生领域事件,这些事件将由传递给总线的 PSR14 调度器自动分发(当在处理程序内调用后续命令时,确保您的事件顺序正确)
  • 在处理程序内执行其他命令

以我们的预订房间示例为例,一个处理程序可能如下所示

class ReserveRoom implements Interfaces\Handler
{
    public function handle(object $command, Interfaces\CommandBus $bus)
    {
        $bus->handle(new Commands\MarkRoomAsReserved($command->getRoom()));
        $bus->handle(new Commands\CompleteInvoiceForRoom($command->getUser(), $command->getRoom()));
         
        yield new Events\RoomWasReserved();
    }
}

中间件

中间件 该库提供。默认执行顺序是后进先出(LIFO),签名非常简单。

public function __invoke(Interfaces\Command $command, callable $next);

中间件必须将命令传递给 $next 可调用函数并执行它以继续命令的执行。

CommandLogger

有助于调试,但最好用于开发和测试环境。