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 Session机制简介及用法
Aug 19 PHP
CentOS6.5 编译安装lnmp环境
Dec 21 PHP
PHP保存带BOM文件的方法
Feb 12 PHP
教大家制作简单的php日历
Nov 17 PHP
CI(CodeIgniter)模型用法实例分析
Jan 20 PHP
PHP如何使用Memcached
Apr 05 PHP
php each 返回数组中当前的键值对并将数组指针向前移动一步实例
Nov 22 PHP
详解thinkphp实现excel数据的导入导出(附完整案例)
Dec 29 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
Aug 31 PHP
使用PHP+MySql+Ajax+jQuery实现省市区三级联动功能示例
Sep 15 PHP
PHP扩展mcrypt实现的AES加密功能示例
Jan 29 PHP
tp5(thinkPHP5框架)时间查询操作实例分析
May 29 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使用memcoder将视频转成mp4格式的方法
2015/03/12 PHP
php倒计时出现-0情况的解决方法
2016/07/28 PHP
使用laravel的Eloquent模型如何获取数据库的指定列
2019/10/17 PHP
javascript开发技术大全-第3章 js数据类型
2011/07/03 Javascript
js 左右悬浮对联广告特效代码
2014/12/12 Javascript
javascript相关事件的几个概念
2015/05/21 Javascript
JavaScript实现点击按钮切换网页背景色的方法
2015/10/17 Javascript
简单实现jQuery级联菜单
2017/01/09 Javascript
nodejs爬虫遇到的乱码问题汇总
2017/04/07 NodeJs
基于js中this和event 的区别(详解)
2017/10/24 Javascript
在Vue项目中引入腾讯验证码服务的教程
2018/04/03 Javascript
JS实现点击按钮随机生成可拖动的不同颜色块示例
2019/01/30 Javascript
[05:40]DOTA2荣耀之路6:Wings最后进攻
2018/05/30 DOTA
Python常用知识点汇总
2016/05/08 Python
Python中字符串的常见操作技巧总结
2016/07/28 Python
tensorflow获取变量维度信息
2018/03/10 Python
Python实现针对给定单链表删除指定节点的方法
2018/04/12 Python
python实现验证码识别功能
2018/06/07 Python
python 异或加密字符串的实例
2018/10/14 Python
python3实现网络爬虫之BeautifulSoup使用详解
2018/12/19 Python
Python 实现数据结构-堆栈和队列的操作方法
2019/07/17 Python
python代码打印100-999之间的回文数示例
2019/11/24 Python
python如何基于redis实现ip代理池
2020/01/17 Python
Python3加密解密库Crypto的RSA加解密和签名/验签实现方法实例
2020/02/11 Python
Python如何操作docker redis过程解析
2020/08/10 Python
Python 爬虫批量爬取网页图片保存到本地的实现代码
2020/12/24 Python
为您的家、后院、车库等在线购物:Spreetail
2019/06/17 全球购物
英国排名第一的餐具品牌:Denby Pottery
2019/11/01 全球购物
公务员转正考察材料
2014/02/07 职场文书
运动会广播稿诗歌版
2014/09/12 职场文书
2014机关干部学习“焦裕禄精神”思想汇报
2014/09/19 职场文书
孕妇离婚协议书范本
2014/11/20 职场文书
2016三八妇女节校园广播稿
2015/12/17 职场文书
简单聊聊Vue中的计算属性和属性侦听
2021/10/05 Vue.js
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL
Go语言编译原理之源码调试
2022/08/05 Golang