この記事では、主に PHP パイプライン プラグイン League\Pipeline の分析を紹介します。このプラグインは一定の参考値があります。ここで共有します。必要な友人は参考にしてください。
水道管は長すぎるため、一部が破損すると水漏れが発生し、複雑な環境での曲げや回転には適していません。そこで、水道管を非常に短い管に分割し、地域の状況に合わせて、さまざまな機能を持たせるために管のサイズを最大化し、組み合わせてさまざまなニーズに対応します。
これは、複雑で長いプロセスを小さなプロセスとタスクに分割するという Pipeline の設計パターンにつながります。最小限に定量化された各タスクは、さまざまな小さなタスクを組み立てることによって、複雑で多様なプロセスを形成するために再利用できます。
最後に、パイプラインに「入力」を導入し、それぞれの小さなタスクに応じて入力を操作(処理、フィルター)し、最終的にニーズに合った結果を出力します。
今日は主に「パイプライン」について勉強します。ちなみに、PHP プラグインは league/pipeline
をお勧めします。
私が「パイプ」の概念について初めて知ったのは、gulp
を使用したときでした。
gulp
は、NodeJS
に基づく自動タスク ランナーです。Javascript
、テストを自動的に完了できます。 、チェック、マージ、圧縮、フォーマット、ブラウザの自動更新、sass
、less
およびその他のファイルのデプロイメント ファイルの生成、変更後に指定された手順を繰り返すためにファイルを監視します。実装に関しては、Unix
オペレーティング システムのパイプのアイデアを利用しており、前のレベルの出力が直接次のレベルの入力になるため、操作が非常に簡単になります。
var gulp = require('gulp'); var less = require('gulp-less'); var minifyCSS = require('gulp-csso'); var concat = require('gulp-concat'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('css', function(){ return gulp.src('client/templates/*.less') .pipe(less()) .pipe(minifyCSS()) .pipe(gulp.dest('build/css')) }); gulp.task('js', function(){ return gulp.src('client/javascript/*.js') .pipe(sourcemaps.init()) .pipe(concat('app.min.js')) .pipe(sourcemaps.write()) .pipe(gulp.dest('build/js')) }); gulp.task('default', [ 'html', 'css', 'js' ]);
上記の 2 つの タスク
は主に、less
およびすべての js
ファイルに対する解析、圧縮、出力、その他の処理操作を行います。対応するフォルダーに保存すると、パイプ内の水の流れと同様に、各ステップの出力が次のステップの入力になります。
Laravel フレームワークのミドルウェアは Illuminate\Pipeline
を使用して実装されています。もともと「Laravel ミドルウェア」のソース コードの解釈について書きたかったのです。しかし、インターネット上にはすでに多くの記事が説明されていることがわかったので、この記事では Illuminate\Pipeline
の使用方法について簡単に説明します。
デモを書く
public function demo(Request $request) { $pipe1 = function ($payload, Closure $next) { $payload = $payload + 1; return $next($payload); }; $pipe2 = function ($payload, Closure $next) { $payload = $payload * 3; return $next($payload); }; $data = $request->input('data', 0); $pipeline = new Pipeline(); return $pipeline ->send($data) ->through([$pipe1, $pipe2]) ->then(function ($data) { return $data; }); }
gulp と
Illuminate\Pipeline の単純な使用法は、「Pipeline」が広く使用されていることを示しています。同様のプラグインを自分で作成するように求められた場合、それは難しくないと思います。
League\Pipeline プラグインを取り上げ、そのソース コードを見て、それがどのように実装されているかを見てみましょう。
簡単な説明
このパッケージは、パイプライン パターンのプラグ アンド プレイ実装を提供します。これは、逐次プロセスをカプセル化するアーキテクチャ パターンです。使用すると、混合することができます。操作とパイプラインを照合して、新しい実行チェーンを作成します。パイプライン パターンは、各ステージが特定のペイロード/サブジェクトに対して特定の操作を実行する生産ラインによく比較されます。ステージは、操作、操作、装飾、さらには置き換えることができますペイロード。特定の主題に関する一連のタスクを完了するために、ある関数から別の関数に結果を渡している場合は、それをパイプラインに変換するとよいでしょう。https://pipeline. thephpleague.com/
プラグインをインストールします
composer require league/pipeline
デモを作成します
use League\Pipeline\Pipeline; // 创建两个闭包函数 $pipe1 = function ($payload) { return $payload + 1; }; $pipe2 = function ($payload) { return $payload * 3; }; $route->map( 'GET', '/demo', function (ServerRequestInterface $request, ResponseInterface $response ) use ($service, $pipe1, $pipe2) { $params = $request->getQueryParams(); // 正常使用 $pipeline1 = (new Pipeline) ->pipe($pipe1) ->pipe($pipe2); $callback1 = $pipeline1->process($params['data']); $response->getBody()->write("<h1>正常使用</h1>"); $response->getBody()->write("<p>结果:$callback1</p>"); // 使用魔术方法 $pipeline2 = (new Pipeline()) ->pipe($pipe1) ->pipe($pipe2); $callback2 = $pipeline2($params['data']); $response->getBody()->write("<h1>使用魔术方法</h1>"); $response->getBody()->write("<p>结果:$callback2</p>"); // 使用 Builder $builder = new PipelineBuilder(); $pipeline3 = $builder ->add($pipe1) ->add($pipe2) ->build(); $callback3 = $pipeline3($params['data']); $response->getBody()->write("<h1>使用 Builder</h1>"); $response->getBody()->write("<p>结果:$callback3</p>"); return $response; } );
実行結果
ソースコードの解釈プラグ全体
PipelineInterface<?php declare(strict_types=1);
namespace League\Pipeline;
interface PipelineInterface extends StageInterface
{
/**
* Create a new pipeline with an appended stage.
*
* @return static
*/
public function pipe(callable $operation): PipelineInterface;
}
interface StageInterface
{
/**
* Process the payload.
*
* @param mixed $payload
*
* @return mixed
*/
public function __invoke($payload);
}
この魔法のメソッドの機能を見てみましょう:
mixed __invoke ([ $... ] )
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。如:
<?php class CallableClass { function __invoke($x) { var_dump($x); } } $obj = new CallableClass; $obj(5); var_dump(is_callable($obj)); ?>
返回结果:
int(5) bool(true)
Pipeline
<?php declare(strict_types=1); namespace League\Pipeline; class Pipeline implements PipelineInterface { /** * @var callable[] */ private $stages = []; /** * @var ProcessorInterface */ private $processor; public function __construct(ProcessorInterface $processor = null, callable ...$stages) { $this->processor = $processor ?? new FingersCrossedProcessor; $this->stages = $stages; } public function pipe(callable $stage): PipelineInterface { $pipeline = clone $this; $pipeline->stages[] = $stage; return $pipeline; } public function process($payload) { return $this->processor->process($payload, ...$this->stages); } public function __invoke($payload) { return $this->process($payload); } }
其中核心类 Pipeline
的作用主要就是两个:
添加组装各个管道「pipe」;
组装后,引水流动,执行 process($payload),输出结果。
Processor
接好各种管道后,那就要「引水入渠」了。该插件提供了两个基础执行类,比较简单,直接看代码就能懂。
// 按照 $stages 数组顺利,遍历执行管道方法,再将结果传入下一个管道,让「水」一层层「流动」起来 class FingersCrossedProcessor implements ProcessorInterface { public function process($payload, callable ...$stages) { foreach ($stages as $stage) { $payload = $stage($payload); } return $payload; } } // 增加一个额外的「过滤网」,经过每个管道后的结果,都需要 check,一旦满足则终止,直接输出结果。 class InterruptibleProcessor implements ProcessorInterface { /** * @var callable */ private $check; public function __construct(callable $check) { $this->check = $check; } public function process($payload, callable ...$stages) { $check = $this->check; foreach ($stages as $stage) { $payload = $stage($payload); if (true !== $check($payload)) { return $payload; } } return $payload; } } interface ProcessorInterface { /** * Process the payload using multiple stages. * * @param mixed $payload * * @return mixed */ public function process($payload, callable ...$stages); }
我们完全也可以利用该接口,实现我们的方法来组装管道和「过滤网」。
PipelineBuilder
最后提供了一个 Builder,这个也很好理解:
class PipelineBuilder implements PipelineBuilderInterface { /** * @var callable[] */ private $stages = []; /** * @return self */ public function add(callable $stage): PipelineBuilderInterface { $this->stages[] = $stage; return $this; } public function build(ProcessorInterface $processor = null): PipelineInterface { return new Pipeline($processor, ...$this->stages); } } interface PipelineBuilderInterface { /** * Add an stage. * * @return self */ public function add(callable $stage): PipelineBuilderInterface; /** * Build a new Pipeline object. */ public function build(ProcessorInterface $processor = null): PipelineInterface; }
无论是对不同技术的横向理解,还是基于 Laravel 或者某些开源插件,我们都能学习到技术之上的通用原理和方法。再将这些原理和方法反作用于我们的实际代码开发中。
最近闲来没事,自己参考 Laravel 去写个简易框架,也将League\Pipeline
引入到框架中使用。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
关于利用Vue-laravel前端和后端分离写一个博客的方法
以上がPHPパイプラインプラグインLeaguePipelineの解析についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。