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 相关文章推荐
PHP安全编程之加密功能
Oct 09 PHP
对squid中refresh_pattern的一些理解和建议
Apr 17 PHP
php数组函数序列之array_intersect() 返回两个或多个数组的交集数组
Nov 10 PHP
PHP设置一边执行一边输出结果的代码
Sep 30 PHP
php中实现精确设置session过期时间的方法
Jul 17 PHP
PHP中使用register_shutdown_function函数截获fatal error示例
Apr 21 PHP
解析WordPress中的post_class与get_post_class函数
Jan 04 PHP
Yii2 GridView实现列表页直接修改数据的方法
May 16 PHP
php获得文件夹下所有文件的递归算法的简单实例
Nov 01 PHP
laravel 5.1下php artisan migrate的使用注意事项总结
Jun 07 PHP
Laravel 6 将新增为指定队列任务设置中间件的功能
Aug 06 PHP
laravel实现登录时监听事件,添加登录用户的记录方法
Sep 30 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无敌近乎加密方式!
2010/07/17 PHP
JS与PHP向函数传递可变参数的区别实例代码
2011/05/18 PHP
PHP在不同页面间传递Json数据示例代码
2013/06/08 PHP
解析array splice的移除数组中指定键的值,返回一个新的数组
2013/07/02 PHP
PHP实现获取FLV文件的时间
2015/02/10 PHP
JScript内置对象Array中元素的删除方法
2007/03/08 Javascript
jQuery基础框架浅入剖析
2012/12/27 Javascript
用JS实现3D球状标签云示例代码
2013/12/01 Javascript
javaScript如何生成xmlhttp
2013/12/16 Javascript
js图片延迟技术一般的思路与示例
2014/03/20 Javascript
js实现div拖动动画运行轨迹效果代码分享
2015/08/27 Javascript
node.js使用cluster实现多进程
2016/03/17 Javascript
JS图片延迟加载插件LazyImgv1.0用法分析【附demo源码下载】
2017/09/04 Javascript
JavaScript实现随机数生成器(去重)
2017/10/13 Javascript
微信小程序实现登录注册tab切换效果
2020/12/29 Javascript
jQuery选择器之基本过滤选择器用法实例分析
2019/02/19 jQuery
JS多个表单数据提交下的serialize()应用实例分析
2019/08/27 Javascript
JS实现随机抽选获奖者
2019/11/07 Javascript
js滚轮事件 js自定义滚动条的实现
2020/01/18 Javascript
Python 学习笔记
2008/12/27 Python
Python定时器实例代码
2017/11/01 Python
python多行字符串拼接使用小括号的方法
2020/03/19 Python
Python的iOS自动化打包实例代码
2018/11/22 Python
python and or用法详解
2019/06/26 Python
我们为什么要减少Python中循环的使用
2019/07/10 Python
Pandas+Matplotlib 箱式图异常值分析示例
2019/12/09 Python
详解python 破解网站反爬虫的两种简单方法
2020/02/09 Python
Python基于Twilio及腾讯云实现国际国内短信接口
2020/06/18 Python
英国时尚优质的女装:Hope Fashion
2018/08/14 全球购物
恶搞卫生巾广告词
2014/03/18 职场文书
信息与工商管理职业规划范文:为梦想而搏击
2014/09/11 职场文书
2015社区六五普法工作总结
2015/04/21 职场文书
退税申请报告怎么写
2015/05/18 职场文书
2015年学校党建工作总结
2015/05/19 职场文书
城南旧事观后感
2015/06/11 职场文书
pytorch 两个GPU同时训练的解决方案
2021/06/01 Python