smartgecko / governor-framework
PHP 命令-查询-职责分离框架。
Requires
- php: 5.5.*
- hamcrest/hamcrest-php: v1.1.1
- jms/serializer: *
- monolog/monolog: 1.8.0
- ocramius/proxy-manager: 0.5.*
- predis/predis: *
- psr/log: @stable
- rhumsaa/uuid: @stable
- symfony/proxy-manager-bridge: >=2.4
- videlalvaro/php-amqplib: 2.2.*
Requires (Dev)
- doctrine/orm: >=2.4
- jms/aop-bundle: 1.1.*@dev
- moontoast/math: *
- phake/phake: 1.*
- phpunit/phpunit: 4.2.*
- symfony/console: >=2.3
- symfony/finder: >=2.3
- symfony/framework-bundle: >=2.4
- symfony/validator: >=2.3
This package is not auto-updated.
Last update: 2024-09-14 16:55:37 UTC
README
Governor Framework 是一个适用于 PHP 5.5+ 的命令和查询职责分离库。
它提供组件来构建遵循 CQRS 模式的应用程序,例如
- 命令处理
- 事件处理
- 事件溯源
- 事件存储
- Sagas
- 工作单元
- 存储库
- 序列化
- AMQP 支持
- 测试
这个库的主要灵感来源是 Java 编写的 Axon 框架,而 Governor 框架可以看作是 Axon 的 PHP 版本,因为它保留了其基本构建块。
这个库可以直接集成到 Symfony 2 框架中作为一个包。Symfony 2 集成的核心来自 LiteCQRS 框架。
快速入门
领域模型
为了展示 Governor 框架的功能,我们将使用一个相当简单的用户模型。用户类是我们的聚合根。在 Governor 中,聚合根必须实现 Governor\Framework\Domain\AggregateRootInterface
接口或扩展内置的基类之一
Governor\Framework\Domain\AbstractAggregateRoot
Governor\Framework\EventSourcing\AbstractEventSourcedAggregateRoot
Governor\Framework\EventSourcing\Annotation\AbstractAnnotatedAggregateRoot
在这个例子中,我们将使用具有注解支持的聚合根。在我们的聚合根中,还将作为示例中的命令处理器。
聚合根将响应以下命令
CreateUserCommand
ChangeUserEmailCommand
这将产生相应的事件
UserCreatedEvent
UserEmailChangedEvent
我们的聚合根实现将如下所示。
class User extends AbstractAnnotatedAggregateRoot { /** * @AggregateIdentifier * @var string */ private $identifier; private $email; /** * @CommandHandler * @param CreateUserCommand $command */ public function __construct(CreateUserCommand $command) { $this->apply(new UserCreatedEvent($command->getIdentifier(), $command->getEmail())); } /** * @CommandHandler * @param ChangeUserEmailCommand $command */ public function changeEmail(ChangeUserEmailCommand $command) { $this->apply(new UserEmailChangedEvent($this->identifier, $command->getEmail())); } /** * @EventHandler * @param UserEmailChangedEvent $event */ public function onEmailChanged(UserEmailChangedEvent $event) { $this->email = $event->getEmail(); } /** * @EventHandler * @param UserCreatedEvent $event */ public function onUserCreated(UserCreatedEvent $event) { $this->identifier = $event->getIdentifier(); $this->email = $event->getEmail(); } public function getEmail() { return $this->email; } }
命令和事件
我们在聚合根上引入了两个操作 - 一个将创建新用户,另一个将更改用户电子邮件。请注意事件类上的 @Type
注解 - Governor 框架使用出色的 JMS 序列化库用于序列化和反序列化。为了在从事件流重新构建聚合根时允许事件反序列化,必须存在注解才能成功反序列化事件。
我们的命令和事件实现如下
abstract class AbstractUserEvent { /** * @Type("string") * @var string */ private $identifier; /** * @Type("string") * @var string */ private $email; function __construct($identifier, $email) { $this->identifier = $identifier; $this->email = $email; } public function getIdentifier() { return $this->identifier; } public function getEmail() { return $this->email; } } class UserCreatedEvent extends AbstractUserEvent { } class UserEmailChangedEvent extends AbstractUserEvent { } abstract class AbstractUserCommand { /** * @TargetAggregateIdentifier * @var string */ private $identifier; private $email; function __construct($identifier, $email) { $this->identifier = $identifier; $this->email = $email; } public function getIdentifier() { return $this->identifier; } public function getEmail() { return $this->email; } } class CreateUserCommand extends AbstractUserCommand { } class ChangeUserEmailCommand extends AbstractUserCommand { }
事件监听器
我们可以注册事件监听器来监听事件总线上的事件。事件监听器需要实现 Governor\Framework\EventHandling\EventListenerInterface
接口。
这是一个简单的监听器,它将监听事件总线上的所有事件并打印它们的负载。
class UserEventListener implements EventListenerInterface { public function handle(EventMessageInterface $event) { print_r($event->getPayload()); } }
整合一切
现在,我们可以通过以下步骤设置必要的基础设施来完成示例
- 我们需要设置一个 PSR-0 兼容的日志记录器,如 Monolog。
- 创建一个命令总线,并为方便将其包装在一个命令网关中。
- 初始化一个基于文件系统的事件存储。请注意,如果您不想使用事件溯源,则可以跳过此步骤。
- 设置一个简单的事件总线
- 创建一个事件溯源存储库
- 将注解聚合根订阅到命令总线,以便它可以接收命令。
- 注册一个将显示事件内容的监听器。
- 分发命令。
// set up logging $logger = new Logger('governor'); $logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG)); // 1. create a command bus and command gateway $commandBus = new SimpleCommandBus(); $commandBus->setLogger($logger); $commandGateway = new DefaultCommandGateway($commandBus); $rootDirectory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'CommandHandlerExample'; @mkdir($rootDirectory); echo sprintf("Initializing FileSystemEventStore in %s\n", $rootDirectory); // 2. initialize the event store $eventStore = new FilesystemEventStore(new SimpleEventFileResolver($rootDirectory), new JMSSerializer()); // 3. create the event bus $eventBus = new SimpleEventBus(); $eventBus->setLogger($logger); // 4. create an event sourcing repository $repository = new EventSourcingRepository(User::class, $eventBus, new NullLockManager(), $eventStore, new GenericAggregateFactory(User::class)); //5. create and register our commands AnnotatedAggregateCommandHandler::subscribe(User::class, $repository, $commandBus); //6. create and register the eventlistener $eventListener = new UserEventListener(); $eventBus->subscribe($eventListener); //7. send commands $aggregateIdentifier = Uuid::uuid1()->toString(); $commandGateway->send(new CreateUserCommand($aggregateIdentifier, 'email@davidkalosi.com')); $commandGateway->send(new ChangeUserEmailCommand($aggregateIdentifier, 'newemail@davidkalosi.com'));
许可
Governor 框架采用 MIT 许可证。