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
drupal 代码实现URL重写
May 04 PHP
解析获取优酷视频真实下载地址的PHP源代码
Jun 26 PHP
PHP imagegrabscreen和imagegrabwindow(截取网站缩略图)的实例代码
Nov 07 PHP
php查询mysql大量数据造成内存不足的解决方法
Mar 04 PHP
php通过curl模拟登陆DZ论坛
May 11 PHP
php metaphone()函数及php localeconv() 函数实例解析
May 15 PHP
功能强大的php文件上传类
Aug 29 PHP
分享PHP-pcntl 实现多进程代码
Sep 30 PHP
弹出模态框modal的实现方法及实例
Sep 19 PHP
php实现的中秋博饼游戏之掷骰子并输出结果功能详解
Nov 06 PHP
Laravel 5.4.36中session没有保存成功问题的解决
Feb 19 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
Netflix将与CLAMP、乙一以及冲方丁等6名知名制作人合伙展开原创动画计划!
2020/03/06 日漫
PHP 查找字符串常用函数介绍
2012/06/07 PHP
ubuntu下编译安装xcache for php5.3 的具体操作步骤
2013/06/18 PHP
PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
2014/07/23 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
2020/03/30 PHP
JavaScript解析URL参数示例代码
2013/08/12 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
jquery插件hiAlert实现网页对话框美化
2015/05/03 Javascript
JavaScript数组迭代器实例分析
2015/06/09 Javascript
跟我学习javascript的垃圾回收机制与内存管理
2015/11/23 Javascript
使用jQuery制作遮罩层弹出效果的极简实例分享
2016/05/12 Javascript
JavaScript仿聊天室聊天记录
2016/12/27 Javascript
vue实现的仿淘宝购物车功能详解
2019/01/27 Javascript
vue计算属性get和set用法示例
2019/02/08 Javascript
详解Vscode中使用Eslint终极配置大全
2019/11/08 Javascript
[02:41]2015国际邀请赛中国区预选赛观战指南
2015/05/20 DOTA
[02:02]特效爆炸!DOTA2珍宝之瓶待你开启
2018/08/21 DOTA
[01:22:28]DOTA2-DPC中国联赛 正赛 SAG vs RNG BO3 第一场 1月18日
2021/03/11 DOTA
Python制作CSDN免积分下载器
2015/03/10 Python
json跨域调用python的方法详解
2017/01/11 Python
200行自定义python异步非阻塞Web框架
2017/03/15 Python
Python Learning 列表的更多操作及示例代码
2018/08/22 Python
python使用matplotlib库生成随机漫步图
2018/08/27 Python
Numpy之reshape()使用详解
2019/12/26 Python
Python使用urllib模块对URL网址中的中文编码与解码实例详解
2020/02/18 Python
新西兰最大的品牌运动鞋购物网站:Platypus NZ
2017/10/27 全球购物
乌克兰排名第一的在线旅游超市:Farvater.Travel
2020/01/02 全球购物
2014村务公开实施方案
2014/02/25 职场文书
2015年幼儿园中班下学期工作总结
2015/05/22 职场文书
2016入党积极分子党课培训心得体会
2016/01/06 职场文书
2019公司管理制度
2019/04/19 职场文书
SQL Server数据定义——模式与基本表操作
2021/04/05 SQL Server
JS异步堆栈追踪之为什么await胜过Promise
2021/04/28 Javascript
python spilt()分隔字符串的实现示例
2021/05/21 Python
Redis如何实现验证码发送 以及限制每日发送次数
2022/04/18 Redis
python 闭包函数详细介绍
2022/04/19 Python