league / pipeline
即插即用型管道实现。
1.0.0
2018-06-05 21:06 UTC
Requires
- php: >=7.1
Requires (Dev)
- leanphp/phpspec-code-coverage: ^4.2
- phpspec/phpspec: ^4.3
This package is auto-updated.
Last update: 2024-09-22 09:54:05 UTC
README
此包提供了一个管道模式实现。
管道模式
管道模式允许您通过链式连接阶段来轻松地组合顺序阶段。
在此特定实现中,接口由两部分组成
- StageInterface
- PipelineInterface
管道由零个、一个或多个阶段组成。管道可以处理有效载荷。在处理过程中,有效载荷将被传递到第一个阶段。从那时起,结果值将从阶段传递到阶段。
在最简单的情况下,执行链可以表示为一个foreach
$result = $payload; foreach ($stages as $stage) { $result = $stage($result); } return $result;
实际上,这与以下相同
$result = $stage3($stage2($stage1($payload)));
不可变性
管道作为不可变阶段链实现。当您连接一个新阶段时,将创建一个新的管道,包含该阶段。这使得管道易于重用,并最小化了副作用。
用法
管道中的操作,阶段,可以是满足callable
类型提示的任何内容。因此,闭包和任何可调用的内容都是好的。
$pipeline = (new Pipeline)->pipe(function ($payload) { return $payload * 10; });
基于类的阶段。
基于类的阶段也是可能的。可以实现StageInterface,这确保了您有正确的__invoke
方法的签名。
use League\Pipeline\Pipeline; use League\Pipeline\StageInterface; class TimesTwoStage implements StageInterface { public function __invoke($payload) { return $payload * 2; } } class AddOneStage implements StageInterface { public function __invoke($payload) { return $payload + 1; } } $pipeline = (new Pipeline) ->pipe(new TimesTwoStage) ->pipe(new AddOneStage); // Returns 21 $pipeline->process(10);
可重用管道
因为PipelineInterface是StageInterface的扩展,所以管道可以作为阶段重用。这创建了一个高度可组合的模型,用于创建复杂的执行模式,同时保持认知负荷低。
例如,如果我们想组合一个处理API调用的管道,我们会创建类似以下的内容
$processApiRequest = (new Pipeline) ->pipe(new ExecuteHttpRequest) // 2 ->pipe(new ParseJsonResponse); // 3 $pipeline = (new Pipeline) ->pipe(new ConvertToPsr7Request) // 1 ->pipe($processApiRequest) // (2,3) ->pipe(new ConvertToResponseDto); // 4 $pipeline->process(new DeleteBlogPost($postId));
管道构建器
因为管道本身是不可变的,所以引入了管道构建器来简化管道的分布式组合。
管道构建器收集阶段,并允许您在给定时间创建一个管道。
use League\Pipeline\PipelineBuilder; // Prepare the builder $pipelineBuilder = (new PipelineBuilder) ->add(new LogicalStage) ->add(new AnotherStage) ->add(new LastStage); // Build the pipeline $pipeline = $pipelineBuilder->build();
异常处理
在此包处理异常时完全透明。在没有任何情况下,此包将捕获异常或静默错误。异常应按每个案例处理。要么在阶段内部,要么在管道处理有效载荷时。
$pipeline = (new Pipeline)->pipe(function () { throw new LogicException(); }); try { $pipeline->process($payload); } catch(LogicException $e) { // Handle the exception. }