手写一个laravel(九) 中间件
- 中间件本质即为闭包
- 使用管道实现,核心为array_reduce函数,因为array_reduce可以将返回值传给下次执行,第一个中间件执行完的结果返回以后可以作为第二个中间件的输入
- 在app/Htpp/Middlewares下创建两个中间件类,用于测试
- 在/app/http下的kernel.php对中间件类进行注册
- 在src下创建建Pipline类
- 将kernel中的路由分发改为由pipline实现
源码见个人git https://github.com/mafa1993/slaravel
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2020/11/23 0023
* Time: 20:54
*/
//用于中间件测试
class MID1
{
public function handle(Closure $next){
echo '中间件1'.PHP_EOL;
$next();
echo '中间件1 end';
}
}
class MID2
{
public function handle(Closure $next){
echo '中间件2'.PHP_EOL;
$next();
echo '中间件2 end';
}
}
class con
{
public function index(){
echo 'con 方法';
}
}
class Pipeline
{
//用来保存需要执行的中间件
protected $pipes = [
MID1::class,
MID2::class
];
public function then(Closure $des){
return array_reduce($this->pipes,function ($res,$pipe){
return function ()use($res,$pipe){
return $pipe::handle($res);
};
},$des);
}
}
$con = function (){
(new con)->index();
};
$pi = new Pipeline();
($pi->then($con))();
/**
* des res pip
* con函数
*
*/
(function (){
ECHO '中间2';
function (){
echo '中间1';
$con();
echo '中间1 end';;
}
ECHO '中间2 end';
})();
pipline类
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2020/11/28 0028
* Time: 16:39
*/
namespace Slaravel\Pipline;
class Pipline
{
protected $pipes;
protected $passable;
protected $app;
protected $method = 'handle';
public function __construct($app)
{
$this->app = $app;
}
public function then(\Closure $closure){
$res = array_reduce(
$this->pipes, //所有需要执行的中间件
$this->carry(),
$closure
);
return $res($this->passable);
}
public function carry(){
return function ($stack,$pipe){
return function ($passable)use($stack,$pipe){
if(is_callable($pipe)){
return $pipe($passable,$stack);
}elseif(!is_object($pipe)){
//类先实例化
$pipe = $this->app->make($pipe);
$params = [$passable,$stack];
}
return method_exists($pipe,$this->method) ? $pipe->{$this->method}(...$params) : $pipe(...$params); //默认执行中间件的handle方法
};
};
}
/*array_reduce(
$this->pipes, //所有需要执行的中间件
function ($passable)use($stack,$pipe){
return $pipe($passable,$stack);
//默认执行中间件的handle方法
;
},
$closure
);
1. $res = mid1::hadle($passable,$con)
2. $res = mid2::hadle($passable,$res())*/
/**
* 用来获取中间件
* @param $pipes
* @return object
*/
public function through($pipes){
$this->pipes = $pipes;
return $this;
}
/**
* @param $passable
* @return object
*/
public function send($passable){
$this->passable = $passable;
return $this;
}
}
网友评论