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 UTF8编码内的繁简转换类
Jul 20 PHP
Can't create/write to file 'C:\WINDOWS\TEMP\...MYSQL报错解决方法
Jun 30 PHP
ajax在joomla中的原生态应用代码
Jul 19 PHP
PHP中数组合并的两种方法及区别介绍
Sep 14 PHP
php+mysql结合Ajax实现点赞功能完整实例
Jan 30 PHP
在Linux系统下一键重新安装WordPress的脚本示例
Jun 30 PHP
php 7新特性之类型申明详解
Jun 06 PHP
PHP常用操作类之通信数据封装类的实现
Jul 16 PHP
PHP二维关联数组的遍历方式(实例讲解)
Oct 18 PHP
PHP与Perl之间知识点区别整理
Mar 19 PHP
laravel config文件配置全局变量的例子
Oct 13 PHP
PhpSpreadsheet设置单元格常用操作汇总
Nov 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
php 将bmp图片转为jpg等其他任意格式的图片
2009/06/29 PHP
php结合安卓客户端实现查询交互实例
2015/05/05 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
2017/09/21 PHP
根据判断浏览器类型屏幕分辨率自动调用不同CSS的代码
2007/02/22 Javascript
javascript编程起步(第六课)
2007/02/27 Javascript
javascript iframe中打开文件,并检测iframe存在否
2008/12/28 Javascript
Jsonp 跨域的原理以及Jquery的解决方案
2011/06/27 Javascript
VBS通过WMI监视注册表变动的代码
2011/10/27 Javascript
使用BootStrap进行轮播图的制作
2017/01/06 Javascript
详解浏览器渲染页面过程
2017/02/09 Javascript
react开发教程之React 组件之间的通信方式
2017/08/12 Javascript
JS实现的简单表单验证功能完整实例
2017/10/14 Javascript
VUE长按事件需求详解
2017/10/18 Javascript
js实现手机web图片左右滑动效果
2017/12/29 Javascript
vue引入新版 vue-awesome-swiper插件填坑问题
2018/01/25 Javascript
BootStrap table实现表格行拖拽效果
2018/12/01 Javascript
了解Javascript中函数作为对象的魅力
2019/06/19 Javascript
javascript 代码是如何被压缩的示例代码
2020/05/06 Javascript
详解vue-router的Import异步加载模块问题的解决方案
2020/05/13 Javascript
python利用跳板机ssh远程连接redis的方法
2019/02/19 Python
Flask框架实现的前端RSA加密与后端Python解密功能详解
2019/08/13 Python
解决pycharm 安装numpy失败的问题
2019/12/05 Python
在python中logger setlevel没有生效的解决
2020/02/21 Python
Python实现验证码识别
2020/06/15 Python
使用Python爬虫爬取小红书完完整整的全过程
2021/01/19 Python
HTML5 Convas APIs方法详解
2015/04/24 HTML / CSS
Paradigit比利时电脑卖场:购买笔记本、电脑、平板和外围设备
2016/11/28 全球购物
详解如何解决使用JSON.stringify时遇到的循环引用问题
2021/03/23 Javascript
环境工程专业自荐信范文
2014/03/18 职场文书
总经理任命书范本
2014/06/05 职场文书
同学聚会致辞集锦
2015/07/28 职场文书
求职信:求职应该注意的问题
2019/04/24 职场文书
写好求职信的技巧解密
2019/05/14 职场文书
2019入党申请书格式
2019/06/25 职场文书
Python合并pdf文件的工具
2021/07/01 Python
CSS SandBox应用场景及常见问题
2022/06/25 HTML / CSS