梦游者 / laravel-doctrine-domain-events
Requires
- php: >=5.6.0
- ext-bcmath: *
- illuminate/validation: ~5.2
- laravel-doctrine/orm: 1.*
- somnambulist/laravel-domain-input-mapper: ~0.5
Requires (Dev)
- illuminate/config: ~5.2
- phpunit/phpunit: ~5.4
- symfony/var-dumper: ~2.8
README
该项目已被替换为一个通用的领域库,将多个包合并为一个,以便于维护。
Laravel-Doctrine ORM的领域事件
向Doctrine实体添加对领域事件的支持。此包受Benjamin Eberlei的Gist和博客文章的启发。
要求
- PHP 5.6+
- bcmath扩展
- Laravel 5.2+
- laravel-doctrine/orm
安装
使用composer安装,或从github.com检查/拉取文件。
- composer install somnambulist/laravel-doctrine-domain-events
- 将事件监听器添加到您的实体管理器配置中的config/doctrine.php
- 将接口添加到您的聚合根(应引发事件的主体实体)
- 将特里特添加以提供接口的实现(或自己编写)
- 添加一些扩展提供的领域事件的领域事件
- 创建一些监听器并将它们附加到doctrine配置中的领域事件
包含一个服务提供者,它添加了编译功能,允许将主要类添加到主要引导中。
- 注意:DomainEventListener应根据实体管理器实例进行配置。
引发事件
要引发事件,请决定哪些操作应导致领域事件。这些应与领域对象的州变化相一致,并且事件应来自您的主体实体(聚合根)。
例如:您可能希望在创建新的User实体或向用户添加角色时引发事件。
这确实需要更改您通常与实体和Doctrine一起工作的方式,您应该删除设置器和可空的构造函数参数。相反,您将需要通过特定方法来管理对实体更改,例如
- completeOrder()
- updatePermissions()
- revokePermissions()
- publishStory()
内部,在更新实体状态后,调用:$this->raise(new NameOfEvent([]))
并将任何特定的参数传递到事件中,您希望使监听器可用。这可能是旧的和新的,或者是整个实体引用,完全取决于您。
public function __construct($id, $name, $another, $createdAt)
{
$this->id = $id;
$this->name = $name;
$this->another = $another;
$this->createdAt = $createdAt;
$this->raise(new MyEntityCreatedEvent(['id' => $id, 'name' => $name, 'another' => $another]));
}
通常,在构造函数中不引发事件更好,而是使用命名构造函数进行主要对象的创建。
private function __construct($id, $name, $another, $createdAt)
{
$this->id = $id;
$this->name = $name;
$this->another = $another;
$this->createdAt = $createdAt;
$this->raise(new MyEntityCreatedEvent(['id' => $id, 'name' => $name, 'another' => $another]));
}
public static function create($id, $name, $another)
{
$entity = new static($id, $name, $another, new DateTime());
$entity->raise(new MyEntityCreatedEvent(['id' => $id, 'name' => $name, 'another' => $another]));
return $entity;
}
触发领域事件
此实现包括一个Doctrine订阅者,它将监听实现RaisesDomainEvent接口的实体,并确保调用releaseAndResetEvents()
。
-
注意:在v.0.6之前,订阅者监听生命周期事件,如果聚合根没有被同时修改,可能会错过事件。
-
注意:不需要使用
DomainEventListener
订阅者。你可以实现自己的事件分发器,完全使用另一个分发器(框架)然后手动通过刷新更改并手动调用releaseAndResetEvents
来触发领域事件。如果你这样做,请注意聚合根类和主标识符(如果使用)将不会自动设置。如果你打算使用它们,需要更新你的代码来设置这些。
要使用包含的监听器,将其添加到Doctrine配置中的事件订阅者列表。这是针对每个实体管理器。
- 注意:要使用依赖于Doctrine存储库的领域事件的监听器,需要在Doctrine解决之后延迟加载这些订阅者。在Laravel中,这可以在服务提供者的
boot
方法中完成。请参阅Laravel Doctrine项目中的示例延迟加载器。
创建领域事件监听器
监听器可以有它们自己的依赖(构造函数未定义),并在onFlush单元工作事件之后被调用。监听器可以执行任何必要的后处理,甚至触发更多事件。
监听器应该添加名为
- onNameOfTheEvent
- 的方法,不附加"event"后缀
- 该方法将接收领域事件实例
- 领域事件将具有聚合根的类和id
单元测试的示例
class EventListener
{
public function onMyEntityCreated(MyEntityCreatedEvent $event)
{
printf(
"New item created with id: %s, name: %s, another: %s",
$event->getProperty('id'),
$event->getProperty('name'),
$event->getProperty('another')
);
}
}
单元测试显示了如何实现它。
务必阅读前面提到的Benjamin Eberlei的文章,并查看他的断言库,用于低依赖项实体验证。
或者,对于挂钩到Laravel主要验证器的验证,请参阅:Laravel Doctrine实体验证。