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 相关文章推荐
COM in PHP (winows only)
Oct 09 PHP
php二维数组排序与默认自然排序的方法介绍
Apr 27 PHP
PHP引用符&amp;的用法详细解析
Aug 22 PHP
ThinkPHP模板之变量输出、自定义函数与判断语句用法
Nov 01 PHP
php将access数据库转换到mysql数据库的方法
Dec 24 PHP
php中fsockopen用法实例
Jan 05 PHP
php统计数组元素个数的方法
Jul 02 PHP
PHP+MySql+jQuery实现的&quot;顶&quot;和&quot;踩&quot;投票功能
May 21 PHP
php无法连接mysql数据库的正确解决方法
Jul 01 PHP
thinkPHP框架自动填充原理与用法分析
Apr 03 PHP
Thinkphp5+uploadify实现的文件上传功能示例
May 26 PHP
PHP设计模式之装饰器模式定义与用法简单示例
Aug 13 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
老机欣赏|中国60年代精品收音机
2021/03/02 无线电
php 攻击方法之谈php+mysql注射语句构造
2009/10/30 PHP
php在window iis的莫名问题的测试方法
2013/05/14 PHP
php模拟ping命令(php exec函数的使用方法)
2013/10/25 PHP
ThinkPHP3.2框架操作Redis的方法分析
2019/05/05 PHP
微信支付之JSAPI公众号支付详解
2019/05/15 PHP
Opacity.js
2007/01/22 Javascript
jquery 问答知识整理
2010/02/11 Javascript
JS简单操作select和dropdownlist实例
2014/11/26 Javascript
angularjs学习笔记之完整的项目结构
2015/09/26 Javascript
深入浅析react native es6语法
2015/12/09 Javascript
jquery分页插件jquery.pagination.js使用方法解析
2016/04/01 Javascript
JavaScipt选取文档元素的方法(推荐)
2016/08/05 Javascript
JavaScript实战之带收放动画效果的导航菜单
2016/08/16 Javascript
jQuery实现字符串全部替换的方法
2016/12/12 Javascript
解析JavaScript数组方法reduce
2016/12/12 Javascript
全面解析jQuery中的$(window)与$(document)的用法区别
2017/08/15 jQuery
利用ES6实现单例模式及其应用详解
2017/12/09 Javascript
判断js数据类型的函数实例详解
2019/05/23 Javascript
搭建一个Koa后端项目脚手架的方法步骤
2019/05/30 Javascript
微信小程序利用Canvas绘制图片和竖排文字详解
2019/06/25 Javascript
uni-app实现获取验证码倒计时功能
2020/11/01 Javascript
python数据结构之二叉树的遍历实例
2014/04/29 Python
Python实现读取TXT文件数据并存进内置数据库SQLite3的方法
2017/08/08 Python
python 递归遍历文件夹,并打印满足条件的文件路径实例
2017/08/30 Python
Python之pandas读写文件乱码的解决方法
2018/04/20 Python
python 集合 并集、交集 Series list set 转换的实例
2018/05/29 Python
tensorflow之读取jpg图像长和宽实例
2020/06/18 Python
Pycharm 2020.1 版配置优化的详细教程
2020/08/07 Python
俄罗斯EPL钻石珠宝店:ЭПЛ
2019/10/22 全球购物
小车司机岗位职责
2013/11/25 职场文书
党员承诺践诺书
2014/05/20 职场文书
2014年置业顾问工作总结
2014/11/17 职场文书
《月球之谜》教学反思
2016/02/20 职场文书
适合毕业生创业的项目怎么找?
2019/08/08 职场文书
「天才王子的赤字国家重生术」妮妮姆·拉雷粘土人开订
2022/03/21 日漫