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


Posted in PHP onApril 26, 2020

Pipeline 设计模式

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

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

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

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

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

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

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' ]);

IlluminatePipeline

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;
    });
}

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

composer require league/pipeline

使用起来也很方便

use League\Pipeline\Pipeline;

class TimesTwoStage
{
  public function __invoke($payload)
  {
    return $payload * 2;
  }
}

class AddOneStage
{
  public function __invoke($payload)
  {
    return $payload + 1;
  }
}

$pipeline = (new Pipeline)
  ->pipe(new TimesTwoStage)
  ->pipe(new AddOneStage);

// Returns 21
$pipeline->process(10);

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

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

上面的代码修改成这样

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

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

<?php
namespace Platapps\Middlewares;
class RespondJson
{
  public function __invoke($payload)
  {
    header('Content-type:text/json');
    return $payload;
  }
}

就简单的加了个 header

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

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

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

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

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

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

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);
  }
}

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

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;

use Closure;
use Exception;
use Throwable;

class Pipeline
{
  protected $passable;

  protected $pipes = [];

  protected $exceptionHandler;

  /**
   * 初始数据
   * @param $passable
   * @return $this
   */
  public function send($passable)
  {
    $this->passable = $passable;
    return $this;
  }

  /**
   * 调用栈
   * @param $pipes
   * @return $this
   */
  public function through($pipes)
  {
    $this->pipes = is_array($pipes) ? $pipes : func_get_args();
    return $this;
  }

  /**
   * 执行
   * @param Closure $destination
   * @return mixed
   */
  public function then(Closure $destination)
  {
    $pipeline = array_reduce(
      array_reverse($this->pipes),
      $this->carry(),
      function ($passable) use ($destination) {
        try {
          return $destination($passable);
        } catch (Throwable | Exception $e) {
          return $this->handleException($passable, $e);
        }
      });

    return $pipeline($this->passable);
  }

  /**
   * 设置异常处理器
   * @param callable $handler
   * @return $this
   */
  public function whenException($handler)
  {
    $this->exceptionHandler = $handler;
    return $this;
  }

  protected function carry()
  {
    return function ($stack, $pipe) {
      return function ($passable) use ($stack, $pipe) {
        try {
          return $pipe($passable, $stack);
        } catch (Throwable | Exception $e) {
          return $this->handleException($passable, $e);
        }
      };
    };
  }

  /**
   * 异常处理
   * @param $passable
   * @param $e
   * @return mixed
   */
  protected function handleException($passable, Throwable $e)
  {
    if ($this->exceptionHandler) {
      return call_user_func($this->exceptionHandler, $passable, $e);
    }
    throw $e;
  }
}

这种写法有什么好?

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

到此这篇关于PHP Pipeline 实现中间件的示例代码的文章就介绍到这了,更多相关PHP Pipeline 中间件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
通过JavaScript或PHP检测Android设备的代码
Mar 09 PHP
PHP禁止页面缓存的代码
Oct 23 PHP
一个PHP的QRcode类与大家分享
Nov 13 PHP
解析crontab php自动运行的方法
Jun 24 PHP
PHP中比较时间大小实例
Aug 21 PHP
PHP产生不重复随机数的5个方法总结
Nov 12 PHP
php技术实现加载字体并保存成图片
Jul 27 PHP
使用Thinkphp框架开发移动端接口
Aug 05 PHP
php操纵mysqli数据库的实现方法
Sep 18 PHP
PHP 布尔值的自增与自减的实现方法
May 03 PHP
php 与 nginx 的处理方式及nginx与php-fpm通信的两种方式
Sep 28 PHP
php项目中类的自动加载实例讲解
Sep 12 PHP
PHP设计模式入门之状态模式原理与实现方法分析
Apr 26 #PHP
PHP设计模式入门之迭代器模式原理与实现方法分析
Apr 26 #PHP
PHP中迭代器的简单实现及Yii框架中的迭代器实现方法示例
Apr 26 #PHP
PHP设计模式之迭代器模式Iterator实例分析【对象行为型】
Apr 26 #PHP
Yii Framework框架开发微信公众平台示例
Apr 26 #PHP
PHP随机生成中文段落示例【测试网站内容时使用】
Apr 26 #PHP
PHP过滤器 filter_has_var() 函数用法实例分析
Apr 23 #PHP
You might like
php全局变量和类配合使用深刻理解
2013/06/05 PHP
php函数间的参数传递(值传递/引用传递)
2013/09/23 PHP
Symfony2学习笔记之系统路由详解
2016/03/17 PHP
关于PHP通用返回值设置方法
2017/03/31 PHP
PHP 中魔术常量的实例详解
2017/10/26 PHP
thinkPHP框架中执行事务的方法示例
2018/05/31 PHP
基于jQuery试卷自动排版系统
2010/07/18 Javascript
如何通过javascript操作web控件的自定义属性
2013/11/25 Javascript
jquery文档操作wrap()方法实例简述
2015/01/10 Javascript
简介JavaScript中valueOf()方法的使用
2015/06/05 Javascript
JS组件系列之Bootstrap Icon图标选择组件
2016/01/28 Javascript
如何利用Promises编写更优雅的JavaScript代码
2016/05/17 Javascript
利用nodejs监控文件变化并使用sftp上传到服务器
2017/02/18 NodeJs
JS中的作用域链
2017/03/01 Javascript
基于VUE移动音乐WEBAPP跨域请求失败的解决方法
2018/01/16 Javascript
JQuery实现ajax请求的示例和注意事项
2018/12/10 jQuery
Python函数参数类型*、**的区别
2015/04/11 Python
使用Python编写提取日志中的中文的脚本的方法
2015/04/30 Python
python从网络读取图片并直接进行处理的方法
2015/05/22 Python
各个系统下的Python解释器相关安装方法
2015/10/12 Python
python 性能提升的几种方法
2016/07/15 Python
Python中numpy模块常见用法demo实例小结
2019/03/16 Python
python 输出列表元素实例(以空格/逗号为分隔符)
2019/12/25 Python
详解Django自定义图片和文件上传路径(upload_to)的2种方式
2020/12/01 Python
HTML5新增的表单元素和属性实例解析
2014/07/07 HTML / CSS
英国领先的品牌珠宝和配件供应商:Acotis Jewellery
2018/03/07 全球购物
沙特阿拉伯排名第一的在线时尚购物应用程序:1Zillion
2020/08/08 全球购物
抄作业检讨书
2014/02/17 职场文书
机电一体化求职信
2014/03/10 职场文书
《北京的春节》教学反思
2014/04/07 职场文书
就职演讲稿范文
2014/05/19 职场文书
大二学生学年自我鉴定
2014/09/12 职场文书
镇党政领导班子民主生活会思想汇报
2014/10/11 职场文书
护士长2015年终工作总结
2015/04/24 职场文书
四年级数学教学反思
2016/02/16 职场文书
李清照的诗词赏析(20首)
2019/08/22 职场文书