当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP Pipeline 实现中间件的示例代码

发布:smiling 来源: PHP粉丝网  添加日期:2022-03-03 09:16:23 浏览: 评论:0 

这篇文章主要介绍了PHP Pipeline 实现中间件的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。

Pipeline 设计模式

水管太长,只要有一处破了,就会漏水了,而且不利于复杂环境弯曲转折使用,所以我们都会把水管分成很短的一节一节管道,然后最大化的让管道大小作用不同,因地制宜,组装在一起,满足各种各样的不同需求。

由此得出 Pipeline 的设计模式,就是将复杂冗长的流程 (processes) 截成各个小流程,小任务。每个最小量化的任务就可以复用,通过组装不同的小任务,构成复杂多样的流程 (processes)。

最后将「输入」引入管道,根据每个小任务对输入进行操作 (加工、过滤),最后输出满足需要的结果。

你可以拿koa的中间件机制来做参考,也就是我们常说的削洋葱思路

在前端里早期有一个工程打包工具gulp写法就更能体现pipeline

  1. gulp.task('css', function(){ 
  2.  return gulp.src('client/templates/*.less') 
  3.   .pipe(less()) 
  4.   .pipe(minifyCSS()) 
  5.   .pipe(gulp.dest('build/css')) 
  6. }); 
  7.  
  8. gulp.task('js', function(){ 
  9.  return gulp.src('client/javascript/*.js') 
  10.   .pipe(sourcemaps.init()) 
  11.   .pipe(concat('app.min.js')) 
  12.   .pipe(sourcemaps.write()) 
  13.   .pipe(gulp.dest('build/js')) 
  14. }); 
  15.  
  16. gulp.task('default', [ 'html', 'css', 'js' ]); 
  17. IlluminatePipeline 

Laravel 框架中的中间件,就是利用 Illuminate\Pipeline 来实现的,本来想写写我对 「Laravel 中间件」源码的解读,但发现网上已经有很多帖子都有表述了,所以本文就简单说说如何使用 Illuminate\Pipeline。

  1. public function demo(Request $request) 
  2. { 
  3.   $pipe1 = function ($payload, Closure $next) { 
  4.     $payload = $payload + 1; 
  5.     return $next($payload); 
  6.   }; 
  7.  
  8.   $pipe2 = function ($payload, Closure $next) { 
  9.     $payload = $payload * 3; 
  10.     return $next($payload); 
  11.   }; 
  12.  
  13.   $data = $request->input('data', 0); 
  14.  
  15.   $pipeline = new Pipeline(); 
  16.  
  17.   return $pipeline 
  18.     ->send($data) 
  19.     ->through([$pipe1, $pipe2]) 
  20.     ->then(function ($data) { 
  21.       return $data; 
  22.     }); 
  23. } 

今天主要学习学习「Pipeline」,顺便推荐一个 PHP 插件:league/pipeline。

composer require league/pipeline

使用起来也很方便

  1. use League\Pipeline\Pipeline; 
  2.  
  3. class TimesTwoStage 
  4. { 
  5.   public function __invoke($payload) 
  6.   { 
  7.     return $payload * 2; 
  8.   } 
  9. } 
  10.  
  11. class AddOneStage 
  12. { 
  13.   public function __invoke($payload) 
  14.   { 
  15.     return $payload + 1; 
  16.   } 
  17. } 
  18.  
  19. $pipeline = (new Pipeline) 
  20.   ->pipe(new TimesTwoStage) 
  21.   ->pipe(new AddOneStage); 
  22.  
  23. // Returns 21 
  24. $pipeline->process(10); 

接下来我们添加FastRouter在我的项目中使用。

上面的代码修改成这样

我们接下来看看 RespondJson 里做了什么.

  1. <?php 
  2. namespace Platapps\Middlewares; 
  3. class RespondJson 
  4. { 
  5.   public function __invoke($payload) 
  6.   { 
  7.     header('Content-type:text/json'); 
  8.     return $payload; 
  9.   } 
  10. } 

就简单的加了个 header

我们试试把注释到一个渠道

我们再次访问的时候就变成

当然这是很简单的中间件,这种中间件远远不够,这里是核心代码,可以去这里看看,也比较简单。

我们最终需要修改pipe这个方法

  1. namespace League\Pipeline; 
  2.  
  3. class Pipeline implements PipelineInterface 
  4. { 
  5.   /** 
  6.    * @var callable[] 
  7.    */ 
  8.   private $stages = []; 
  9.  
  10.   /** 
  11.    * @var ProcessorInterface 
  12.    */ 
  13.   private $processor; 
  14.  
  15.   public function __construct(ProcessorInterface $processor = null, callable ...$stages) 
  16.   { 
  17.     $this->processor = $processor ?? new FingersCrossedProcessor; 
  18.     $this->stages = $stages; 
  19.   } 
  20.  
  21.   public function pipe(callable $stage): PipelineInterface 
  22.   { 
  23.     $pipeline = clone $this; 
  24.     $pipeline->stages[] = $stage; 
  25.  
  26.     return $pipeline; 
  27.   } 
  28.  
  29.   public function process($payload) 
  30.   { 
  31.     return $this->processor->process($payload, ...$this->stages); 
  32.   } 
  33.  
  34.   public function __invoke($payload) 
  35.   { 
  36.     return $this->process($payload); 
  37.   } 
  38. } 

这么多框架里面我这里建议拿Tp6的来做参考,功能还算够用。

  1. <?php 
  2. // +---------------------------------------------------------------------- 
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ] 
  4. // +---------------------------------------------------------------------- 
  5. // | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved. 
  6. // +---------------------------------------------------------------------- 
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 
  8. // +---------------------------------------------------------------------- 
  9. // | Author: yunwuxin <448901948@qq.com> 
  10. // +---------------------------------------------------------------------- 
  11. namespace think; 
  12.  
  13. use Closure; 
  14. use Exception; 
  15. use Throwable; 
  16.  
  17. class Pipeline 
  18. { 
  19.   protected $passable; 
  20.  
  21.   protected $pipes = []; 
  22.  
  23.   protected $exceptionHandler; 
  24.  
  25.   /** 
  26.    * 初始数据 
  27.    * @param $passable 
  28.    * @return $this 
  29.    */ 
  30.   public function send($passable) 
  31.   { 
  32.     $this->passable = $passable; 
  33.     return $this; 
  34.   } 
  35.  
  36.   /** 
  37.    * 调用栈 
  38.    * @param $pipes 
  39.    * @return $this 
  40.    */ 
  41.   public function through($pipes) 
  42.   { 
  43.     $this->pipes = is_array($pipes) ? $pipes : func_get_args(); 
  44.     return $this; 
  45.   } 
  46.  
  47.   /** 
  48.    * 执行 
  49.    * @param Closure $destination 
  50.    * @return mixed 
  51.    */ 
  52.   public function then(Closure $destination) 
  53.   { 
  54.     $pipeline = array_reduce( 
  55.       array_reverse($this->pipes), 
  56.       $this->carry(), 
  57.       function ($passable) use ($destination) { 
  58.         try { 
  59.           return $destination($passable); 
  60.         } catch (Throwable | Exception $e) { 
  61.           return $this->handleException($passable, $e); 
  62.         } 
  63.       }); 
  64.  
  65.     return $pipeline($this->passable); 
  66.   } 
  67.  
  68.   /** 
  69.    * 设置异常处理器 
  70.    * @param callable $handler 
  71.    * @return $this 
  72.    */ 
  73.   public function whenException($handler) 
  74.   { 
  75.     $this->exceptionHandler = $handler; 
  76.     return $this; 
  77.   } 
  78.  
  79.   protected function carry() 
  80.   { 
  81.     return function ($stack, $pipe) { 
  82.       return function ($passable) use ($stack, $pipe) { 
  83.         try { 
  84.           return $pipe($passable, $stack); 
  85.         } catch (Throwable | Exception $e) { 
  86.           return $this->handleException($passable, $e); 
  87.         } 
  88.       }; 
  89.     }; 
  90.   } 
  91.  
  92.   /** 
  93.    * 异常处理 
  94.    * @param $passable 
  95.    * @param $e 
  96.    * @return mixed 
  97.    */ 
  98.   protected function handleException($passable, Throwable $e) 
  99.   { 
  100.     if ($this->exceptionHandler) { 
  101.       return call_user_func($this->exceptionHandler, $passable, $e); 
  102.     } 
  103.     throw $e; 
  104.   } 
  105. } 

这种写法有什么好?

其实就好就好在,你在处理一个请求的过程中,分配任务的时候,在处理的过程,每个中间的人,只要做自己处理的请求和结果还有请求即可,让当数据到达Controller里的时候,显示业务逻辑的时候更加强大

Tags: Pipeline PHP中间件

分享到: