zeeloengineering / php-shared-kernel
为DDD应用提供的简单共享内核,包含许多适用于六边形架构、事件源等的脚手架代码。
Requires
- doctrine/orm: ^2.5
- guzzlehttp/guzzle: ^6.3
- php-amqplib/php-amqplib: ^2.7
- ramsey/uuid: ^3.7
Requires (Dev)
- phpunit/phpunit: ^6.5
- dev-master
- 0.85
- 0.84
- 0.83
- 0.82
- 0.81
- 0.8
- 0.7
- 0.6
- 0.5
- 0.4
- 0.3
- 0.2
- 0.1
- dev-encrypted_entity
- dev-relationsQueryBuilder
- dev-addingFindAllToEventSourcedRepositoryInterface
- dev-dev
- dev-update_core_relations
- dev-alberthorta-patch-1
- dev-AllowTextCriteriaItemToMatchNullValues
- dev-AddingClearToReadModel
- dev-BuildEventFromData
- dev-AddingListableQuery
- dev-AddingPageableCollection
- dev-AddingCriteria
- dev-AddingLimitAndOffsetToReadModelRepository
- dev-AddingReadModel
- dev-AddingDeleteToRepository
- dev-AddingEntityDisablingCapabilities
- dev-AddingEventSourcingCapabilities
- dev-RemovingToArrayFromEntity
- dev-AddingCriteriaToRepository
This package is auto-updated.
Last update: 2024-09-18 21:25:36 UTC
README
为DDD应用提供的简单共享内核,包含许多适用于六边形架构、事件源等的脚手架代码。
实体
您可以通过从Entity类继承来创建一个新的实体。
<?php use StraTDeS\SharedKernel\Domain\Entity; use StraTDeS\SharedKernel\Domain\Id; class Person extends Entity { private $name; private $surname; public function __construct(Id $id, string $name, string $surname) { parent::__construct($id); $this->name = $name; $this->surname = $surname; } public function getName(): string { return $this->name; } public function getSurname(): string { return $this->surname; } }
实现构造函数是强制性的,因为Id由基类控制。
只要您继承了Entity,您就有EventStreamAvailable,因此您可以记录事件并检索EventStream。
<?php use StraTDeS\SharedKernel\Domain\Entity; use StraTDeS\SharedKernel\Domain\Id; use StraTDeS\SharedKernel\Domain\UUIDV4; class Person extends Entity { private $name; private $surname; public function __construct(Id $id, string $name, string $surname) { parent::__construct($id); $this->name = $name; $this->surname = $surname; $this->recordThat( new PersonCreated( UUIDV4::generate(), $this->getId(), $name, $surname ) ); } public function getName(): string { return $this->name; } public function getSurname(): string { return $this->surname; } } $person = new Person( UUIDV4::generate(), 'Alex', 'Hernández' ); $eventStream = $person->pullEventStream();
实体集合
由于您最终将从存储库返回实体的数组,我已经为您准备了一个简单的实体集合,您可以直接继承。
<?php use StraTDeS\SharedKernel\Domain\EntityCollection; use StraTDeS\SharedKernel\Domain\UUIDV4; class PersonCollection extends EntityCollection { } $personCollection = new PersonCollection([ new Person( UUIDV4::generate(), 'Alex', 'Hernández' ), new Person( UUIDV4::generate(), 'John', 'Smith' ) ]); $entities = $personCollection->getEntities();
领域事件
当您想要创建一个事件时,您可以从一个基类DomainEvent继承。就是这样简单。
<?php use StraTDeS\SharedKernel\Domain\DomainEvent; use StraTDeS\SharedKernel\Domain\Id; class PersonCreated extends DomainEvent { private $name; private $surname; public function __construct(Id $id, Id $entityId, string $name, string $surname) { parent::__construct($id, $entityId); $this->name = $name; $this->surname = $surname; } public function getName(): string { return $this->name; } public function getSurname(): string { return $this->surname; } }
用例
通过Application UseCase,您可以从控制台命令或控制器中非常简单地访问领域和基础设施层。一个UseCase接收一个请求,并可能返回(或null)一个响应。让我们看看一个例子。
<?php use StraTDeS\SharedKernel\Application\UseCase\UseCase; use StraTDeS\SharedKernel\Application\UseCase\Request; use StraTDeS\SharedKernel\Application\UseCase\Response; use StraTDeS\SharedKernel\Domain\Id; use StraTDeS\SharedKernel\Application\DataTransformer; class PersonCollectionToArrayDataTransformer implements DataTransformer { /** * @param mixed|PersonCollection $data * @return array */ public function transform(mixed $data): mixed { $persons = []; foreach($data as $person) { $persons[] = $person->toArray(); } return $persons; } } class GetUserByIdRequest extends Request { private $id; public function __construct(Id $id) { $this->id = $id; } public function getId(): Id { return $this->id; } } class GetUserByIdResponse extends Response { private $persons; public function __construct(mixed $persons) { $this->persons = $persons; } public function getPersons(): mixed { return $this->persons; } } class GetUserByIdUseCase extends UseCase { private $dataTransformer; public function __construct(DataTransformer $dataTransformer) { $this->dataTransformer = $dataTransformer; } public function execute(Request $getUserByIdRequest): Response { $userCollection = //my repository query returns a PersonCollection return new GetUserByIdResponse($this->dataTransformer->transform($userCollection)); } }
您可能已经注意到了DataTransformer对象。它提供了将任何对象转换成应用程序层中任何其他对象的功能。这意味着您可以通过注入不同的数据转换器来使用相同的UseCase以不同的格式检索信息。这是基本的不将领域对象返回给基础设施层的方法。
我建议根据注入的数据转换器定义不同的用例名称。例如
- get_user_by_id_use_case_data_transformed_to_array
- get_user_by_id_use_case_data_transformed_to_json
如果您使用了一个不错的依赖注入器,这可以很容易地完成。
CQRS
CQRS代表命令查询责任分离,基本上意味着一个方法应该要么返回一个值,要么修改其上下文,但不要同时做这两件事。
我提供了一些有用的接口,既可以用于命令(以更改上下文),也可以用于查询(以检索信息)。这通常通过命令和查询总线来完成。总线接受某种类型的请求(一个命令或一个查询)并通过处理器(一个CommandHandler或一个QueryHandler)处理它。可以在处理过程中添加中间件。
因此,在namespace StraTDeS\SharedKernel\Application\CQRS中有命令和查询的抽象类,以及命令处理器和查询处理器的接口。
存储库
有一些有用的接口可以实现存储库,包括get、find、all接口和save接口。此外,我还包括两个基本的Doctrine存储库,DoctrineRepository和DoctrinePersistentRepository。您可以使用它来免费获得一些功能。
<?php use StraTDeS\SharedKernel\Infrastructure\DoctrinePersistentRepository; use StraTDeS\SharedKernel\Domain\UUIDV4; class DoctrinePersonRepository extends DoctrinePersistentRepository implements PersonRepository { public function getEntityName(): string { return Person::class; } } // person repository creation ... $person = $personRepository->get(UUIDV4::fromString('6238ec41-71d0-4482-97f5-4c5c4919e635')); $person->changeName('John'); $personRepository->save($person);