baron / pipeline
dev-master
2024-03-19 08:00 UTC
Requires
- php: ^8.1
- psr/container: ^2.0
Requires (Dev)
- phpspec/prophecy-phpunit: ^2.2
- phpstan/phpstan: ^1.2
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5
- roave/security-advisories: dev-master
This package is auto-updated.
Last update: 2024-09-19 08:59:21 UTC
README
使用这个库,我们可以将长执行分离成多个任务。管道使你能够更好地满足单一职责的要求。这导致更好的可维护性和可测试性。
如何使用
- 管道将有效载荷及其自身传递给任务。
public function __invoke(PayloadInterface $payload, PipelineInterface $pipeline): PayloadInterface;
- 第一个任务调用下一个任务,调用下一个任务,调用下一个任务...
$payloadAfterAllSteps = $pipeline->handle($payload);
- 就像在 PSR-7(请求对象)中一样,你现在能够通过添加和从有效载荷对象获取信息来处理所有信息
$value = $genericPayload->getValue();
$value++;
$genericPayload->setValue($value);
步骤详解
- 创建任务(s)
- 初始化管道
- 填充有效载荷
- 执行管道
- 评估管道
使用管道服务
你可以简单地从你的DI(需要PSR-11容器服务管理器)创建管道。这只需要两行代码(+配置)
PipelineService
类允许你将任务作为服务散列传递。
// .. In your factory $tasksFromEnvConfig = $config->getTasks() // somewhere in your config: [Task1::class, Task2::class, Task3::class]; $pipeline = (new PipelineService)->createPsr11($serviceManager, $tasksFromEnvConfig);
使用 mbaron/Pipeline,你可以快速创建复杂任务
// Configuration of BiPRO Request (= German XML Request Standard) $tasklist = [ CheckServiceAvailabilityTask::class, [ // do Request ErrorHandlerTask::class, // catch execution of submission even on error [ PrepareDataTask::class, ValidateDataTask::class, DoGetOfferRequestTask::class ], // .. some additional things like set quote, upload documents etc. ], [ // do something additionally LogResultLocalyTask::class, LogResultInDWTask::class, ] ];
最佳实践
- 使用
RecursivePipeline
创建“子管道”=> 动态任务 - 由于结构,每个任务都有一个“处理下一个步骤之前”和“处理下一个步骤之后”
- 通过抛出异常或返回未处理的下一个步骤的有效载荷来中断管道
示例
手动初始化管道
当然,最好总是使用DI而不是new
// Create Tasks in order of execution $tasks = [ new ExceptionTask(), new ErrorBagTask(), new OpenStreamTask(), new ReadValuesTask(), new ValidateValuesTask(), new RequireDocumentsTask(), new HandleImportTask(), ]; // Create Pipeline $pipeline = new \mbaron\Pipeline\Pipeline($tasks); // Create Payload $payload = new ImportPayload(); // Setup Payload $payload->setEnvironment($env); // <= here you also could use $pipeline->setOptions(...) $payload->setConfig($config); // Do the thing the pipeline is constructed for $payload = $pipeline->handle($payload); // Evaluate result $payload->getMessage();
简单的执行某些操作的任务
使用管道对象传递配置和处理任务之间的数据
public function __invoke(PayloadInterface $payload, PipelineInterface $pipeline): PayloadInterface { // there is something, so we need to continue with our tasks if ($payload->getValue() > 0) { return $pipeline->handle($payload); } // we do not allow negative values => Completely interrupt process if ($payload->getValue() < 0) { throw new \Exception("Negative Values are not allowed here"); } // Value is 0, let's pretend there is nothing more to do. => Interrupt from here and go back up the callstack return $payload; }
异常处理任务
在管道中处理(可能只是某些)异常
public function __invoke(PayloadInterface $payload, PipelineInterface $pipeline): PayloadInterface { try { // handle next steps BEFORE doing something $payload = $pipeline->handle($payload); } catch (\Throwable $e) { $this->logger->logException($e, ['context' => $payload]); } return $payload; }
错误包
使用错误包处理多个错误
public function __invoke(PayloadInterface $payload, PipelineInterface $pipeline): PayloadInterface { // Do something before handle next steps $payload->setErrorBag($this->errorBag); // Pipeline will add errors to error bag $payload = $pipeline->handle($payload); // "On the way back" and after handling, we check if something is inside the error bag if ($payload->getErrorBag()->hasErrors()) { $payload->setMessage($payload->getErrorBag()->toString()); } return $payload; }