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 相关文章推荐
一个显示天气预报的程序
Oct 09 PHP
不用数据库的多用户文件自由上传投票系统(1)
Oct 09 PHP
用PHP读取flv文件的播放时间长度
Sep 03 PHP
解析CI即CodeIgniter框架在Nginx下的重写规则
Jun 03 PHP
PHP实现加密的几种方式介绍
Feb 22 PHP
PHP如何通过AJAX方式实现登录功能
Nov 23 PHP
CodeIgniter分页类pagination使用方法示例
Mar 28 PHP
PHP类相关知识点实例总结
Sep 28 PHP
php双层循环(九九乘法表)
Oct 23 PHP
CI框架网页缓存简单用法分析
Dec 26 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
Mar 29 PHP
PHP SESSION跨页面传递失败解决方案
Dec 11 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
简单的页面缓冲技术
2006/10/09 PHP
分享一个超好用的php header下载函数
2014/01/31 PHP
php获取指定日期之间的各个周和月的起止时间
2014/11/24 PHP
ThinkPHP简单使用memcache缓存的方法
2016/11/15 PHP
javascript 浏览器检测代码精简版
2010/03/04 Javascript
Mootools 图片展示插件(lightbox,ImageMenu)收集集合
2010/05/21 Javascript
juqery 学习之五 文档处理 包裹、替换、删除、复制
2011/02/11 Javascript
a标签click和href执行顺序探讨
2014/06/23 Javascript
微信企业号开发之微信考勤百度地图定位
2015/09/11 Javascript
JavaScript 节流函数 Throttle 详解
2016/07/04 Javascript
javascript中Date对象应用之简易日历实现
2016/07/12 Javascript
详解Angular中$cacheFactory缓存的使用
2016/08/19 Javascript
js 只比较时间大小的实例
2017/10/26 Javascript
关于laydate.js加载laydate.css路径错误问题解决
2017/12/27 Javascript
微信头像地址失效踩坑记附带解决方案
2019/09/23 Javascript
使用Bootstrap做一个朝代历史表
2019/12/10 Javascript
[46:55]完美世界DOTA2联赛决赛 FTD vs Phoenix 第三场 11.08
2020/11/11 DOTA
[03:17]DOTA2-DPC中国联赛1月29日Recap集锦
2021/03/11 DOTA
python实现数通设备端口监控示例
2014/04/02 Python
Pyqt实现无边框窗口拖动以及窗口大小改变
2018/04/19 Python
利用pyinstaller将py文件打包为exe的方法
2018/05/14 Python
python实现zabbix发送短信脚本
2018/09/17 Python
用python标准库difflib比较两份文件的异同详解
2018/11/16 Python
Python利用scapy实现ARP欺骗的方法
2019/07/23 Python
pytorch神经网络之卷积层与全连接层参数的设置方法
2019/08/18 Python
离线状态下在jupyter notebook中使用plotly实例
2020/04/24 Python
如何用Matplotlib 画三维图的示例代码
2020/07/28 Python
澳大利亚个性化儿童礼品网站:Bright Star Kids
2019/06/14 全球购物
《沉香救母》教学反思
2014/04/19 职场文书
禁毒宣传标语
2014/06/19 职场文书
培训通知书模板
2015/04/17 职场文书
工程竣工验收申请报告
2015/05/15 职场文书
Redis实现订单自动过期功能的示例代码
2021/05/08 Redis
关于antd tree 和父子组件之间的传值问题(react 总结)
2021/06/02 Javascript
铁拳制作人赞《铁拳7》老头环Mod:制作精良 但别弄了
2022/04/03 其他游戏
Python作用域和名称空间的详细介绍
2022/04/13 Python