zemd / micro
微服务路由和处理组件
Requires
- php: >=5.6
- ocramius/generated-hydrator: ^1.2
This package is not auto-updated.
Last update: 2023-02-04 10:31:05 UTC
README
轻量级领域驱动REST API架构
安装
composer require zemd/micro
使用
这是一种轻量级方法来管理REST API调用,将它们转换为漂亮的领域对象,并路由到处理器。这种方法可以避免在处理API请求时出现杂乱的样板代码。
因此,您有一些处理“请求”并返回一些数据的特定代码。这是一段独立的代码,可以放置在RabbitMQ消费者或其他网络位置。我们可以称之为 处理器,并定义每个这样的处理器都必须实现简单的方法 handle
。
由于这样的 处理器
不了解它接收的HTTP请求,因此在其参数中包含一些 命令 对象。它只是一个可序列化对象,可以通过任何传输机制传输而不会丢失数据。
class FeatureHandler implements HandlerInterface { public function handle(CommandInterface $command, $context) { // do stuff return "response"; } }
为了让它对某些路由器可访问,需要传递一些关于您的端点和其目标的 元信息。在端点可以物理地放置在不同服务器的系统中,您可以在目标服务中共享元信息,并以 HandlerMetaInterface 接口的实例返回收集到的信息。
class FeatureMetaInformation implements HandlerMetaInterface { public function getMethods() { return ['GET']; } // Unique string that match handler name, it should be possible to be constructed from request string public function getEndpoint() { return '/users/search'; } public function getCommandGuesser() { return false; // If false returns getCommandClass() method will be used. } public function getCommandClass() { return 'my.command.as.service'; // or FeatureCommand::class } public function getDescription() { return 'Some cool feature'; } }
请记住在 services.yml 中标记您的元信息提供者
my.feature.handler.meta.information: class: Namespace\To\My\FeatureMetaInformation tags: - zemd.micro.handler_meta
现在我们有了信息和处理器,我们可以继续构建 命令。命令通过 CommandBuilder 自动构建,因此您只需通过传递使用注解的附加信息来定义它,并将其提供给构建器和处理器。
@RequestParam
- 表示属性的值在请求中定义在期望的别名下,可以定义自定义模式进行验证,并设置此参数是否为构建命令所必需。
@Type
- 表示属性定义为对象类型
如果您愿意,可以定义自己的注解。
class FeatureCommand implements CommandInterface { /** * @RequestParam("mobile", pattern="\+\d{8,13}", required=true) * @Type("\My\Project\ValueObjects\MobileObject") * @Constraints\NotNull() */ protected $mobile; /** * @RequestParam("country_code", required=false) * @Type("\My\Project\ValueObjects\CountryInfoObject") */ protected $countryInfo; /** * @RequestParam("lang", required=false) */ protected $lang; // ... getters/setters/serialize/unserialize }
如您所见,这个类是纯领域对象,没有任何复杂性。
因此,我们现在有了 处理器、元信息 和 命令,我们已可以启动我们的命令管道。我们可以定义一个控制器操作,该操作将负责处理所有API调用。
class TestController { public function handleAction($param1, $param2, $param3, Request $request) { $checkpoint = "$param1/$param2/$param3"; $handlerMetaManager = new HandlerMetaManager(); $handlerMeta = $handlerMetaManager->getMeta($checkpoint); $commandBuilder = new CommandBuilder(); // in case command guesser returns service id, container must be passed to builder $commandBuilder->setContainer($container); $command = $commandBuilder->setRequest($request) ->setMeta($handlerMeta) ->build(); $handlerDispatcher = new CommandDispatcher($config); $result = $handlerDispatcher->dispatch($command); // now we have $result with response // we can serialize it in json/xml/... return $result; } }
高级使用
到目前为止,我们构建了一个放置在同一台机器上的简单处理器。但如果我们想使其分布式和异步,该怎么办呢。您可以通过实现 CommandDispatcherInterface
来实现这一点。默认情况下,CommandDispatcher
通过 old_sound_rabbit_mq 包支持 rabbitmq。这要求您实现 Consumer
,在它内部,您应将命令传递给处理器,并使用 rabbitmq xml/rpc 机制返回响应。在这种架构中,您可以实现简单的 map/reduce 处理器或异步地在处理器中运行几个重量级计算,然后返回结果。
许可证
Micro 在 MIT 许可证下发布。