lmc/ cqrs-types
包含用于查询和命令的类型(接口和值对象)的库,有助于处理查询和命令
Requires
- php: ^8.2
- ext-hash: *
- ext-json: *
- ext-mbstring: *
- psr/cache: ^2.0 || ^3.0
- psr/http-client: ^1.0
- psr/http-message: ^1.0 || ^2.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.5
- lmc/coding-standard: ^3.3
- php-parallel-lint/php-parallel-lint: ^1.2
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^1.4
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^11.0.4
README
这个库包含CQRS库的类型(值对象、接口和基本实现)。因此,任何人都可以轻松地为它编写扩展。
目录
安装
composer require lmc/cqrs-types
接口(类型)
这里有许多接口和类型,这些在 其他CQRS库 中实现
查询接口
所有查询的主要接口。查询是一个获取数据而不更改任何内容的请求。它负责声明和创建一个请求,该请求将由 QueryHandlerInterface
处理。实现查询接口的对象可以实施 功能,并且应由一个 QueryFetcher
处理。
可用的特性
- 缓存
- 性能分析
查询检索器接口
查询检索器的接口(见 处理器/查询检索器)。
它负责
- 根据查询请求类型查找查询处理器
- 处理所有查询特性
- 缓存
- 需要
Psr\Cache\CacheItemPoolInterface
的一个实例
- 需要
- 性能分析
- 需要
Lmc\Cqrs\Handler\ProfilerBag
的一个实例
- 需要
- 缓存
- 解码来自查询处理器的响应
查询处理器接口
它负责处理特定的查询请求并将结果传递给 OnSuccess
回调。它必须声明它支持哪些请求,并且它不能处理不同的请求。当传递不支持的处理方法请求时,它必须在 OnError
回调中传递 UnsupportedRequestException
。它不能抛出任何异常,所有异常都必须传递到 OnError
回调。
如果需要,它可以准备一个查询(例如注入客户端)——但 prepare
方法不应更改查询类型或其内容。它应该仅准备支持的查询。它也不应抛出任何异常。
命令接口
所有命令的主要接口。命令是一个更改数据并可能返回结果数据的请求。它负责声明和创建一个请求,该请求将由 SendCommandHandlerInterface
处理。实现命令接口的对象可以实施 功能,并且应由一个 CommandSender
处理。
可用的特性
- 性能分析
命令发送者接口
命令发送者的接口(见 处理器/命令发送者)。
它负责
- 根据命令请求类型查找发送命令处理器
- 处理所有命令特性
- 性能分析
- 需要
Lmc\Cqrs\Handler\ProfilerBag
的一个实例
- 需要
- 性能分析
- 解码来自发送命令处理器的响应
发送命令处理器接口
负责处理特定的命令请求,并将结果传递给 OnSuccess
回调。它必须声明支持哪些请求,并且不能处理不同的请求。当将不支持请求传递给处理方法时,它必须将 UnsupportedRequestException
传递给 OnError
回调。它不能抛出任何异常,所有异常都必须传递给 OnError
回调。
如果需要,它可以准备一个命令(例如注入客户端)——但是 prepare
方法不应改变命令类型或其内容。它应该只准备支持的命令。它也不能抛出任何异常。
响应解码器接口
用于解码响应(无论是 QueryHandlerInterface
还是 SendCommandHandlerInterface
的结果)。解码器本身应该尽可能小,并且只支持一种解码类型。解码器应按优先级逐个使用(默认实现就是这样)。
如果您需要一个解码器是 final 且不进行其他解码,您必须返回一个 DecodedValue
对象。
- QueryFetcher 和 CommandSender 负责不将
DecodedValue
发送到任何其他解码器
它应该是纯的。
响应应该以相同的方式解码,在这种情况下,可以安全地将其缓存。
如果您需要在解码器中执行一些不纯的操作,请改用 ImpureResponseDecoderInterface
。它与纯解码器工作方式完全相同,但额外的 QueryFetcher
知道解码过程不是纯的,因此它可以做一些额外的事情。例如,QueryFetcher
应在第一次不纯解码之前缓存结果,以免缓存错误的结果。
如果将不支持响应传递给解码方法,则应返回它未改变。它不能抛出异常。
还有一个预定义的响应解码器,用于将 json 字符串解码为数组 —— JsonResponseDecoder
。
分析器格式化器接口
当命令或查询实现 Feature\ProfileableInterface
时,QueryFetcher/CommandSender 将创建一个包含一些信息的 ProfilerItem
。该 ProfilerItem
包含有关持续时间、请求类型、响应、错误等原始数据,并旨在在 Symfony 分析器中显示(如果您使用了一个 CQRS 扩展包)。分析器格式化器将这些项目格式化,以提供比原始数据更好的体验,而原始数据可能难以阅读或不可读。它负责将 ProfilerItem
格式化为另一个 ProfilerItem
,以便可以获取/设置所有 ProfilerItem
属性。
有一个 FormattedValue
值对象,用于帮助格式化,它可以传递给大多数 ProfilerItem
属性作为值。它包含原始值和格式化值。
分析器格式化器甚至可以进一步格式化已格式化的 FormattedValue
。应按优先级逐个调用多个格式化器对 ProfilerItem
进行格式化,以创建最可读的 ProfilerItem
形式。
还有一个预定义的分析器格式化器,用于将 json 字符串格式化(解码)为数组 —— JsonProfilerFormatter
。
特性
可缓存接口
它允许将实现此接口的对象存储和加载到 Psr\Cache\CacheItemPoolInterface
。它使用一个尽可能唯一的 CacheKey
。
注意:还需要设置 Psr\Cache\CacheItemPoolInterface
实现到 QueryFetcher
。
可分析接口
它允许对实现此接口的对象进行分析。 ProfilerId
是一个字符串,它不必是唯一的。
基本实现
基本实现提供了一种(些)方法,这些方法在实现处理器等时通常会被需要。
处理器
AbstractQueryHandler
和AbstractSendCommandHandler
为处理方法提供的给定命令/查询的基类实现,以及基类 prepare
方法,后者不对查询/命令进行任何操作(因为大多数处理器不需要它)。
其使用方法如下
class MyQueryHandler extends AbstractQueryHandler { public function supports(QueryInterface $query): bool { return $query->getRequestType() === ExpectedRequestClass::class; } public function handle(QueryInterface $query, OnSuccessInterface $onSuccess, OnErrorInterface $onError): void { if (!$this->assertIsSupported(ExpectedRequestClass::class, $query, $onError)) { return; } try { $response = ...; // handle query/command ... $onSuccess($response); } catch (\Throwable $e) { $onError($e); } } }
解码器
CallbackResponseDecoder
如果您需要一种快速解码响应的方法,可以使用此回调响应解码器,该解码器允许您传递一个用于解码的函数。
$decoder = new CallbackResponseDecoder( fn (string $response, $initiator) => is_string($response), fn (string $response) => sprintf('decoded:%s', $response), );
JsonResponseDecoder
它将包含json的字符串解码成解码数组。