Laravel框架MiddleWare实现原理demo

根据Laravel框架中间件的实现机制,写的一个实现demo。
GitHub源码
- 关键在于PipeLine类的then方法:
- 其中最关键的是array_reduce( array, a r r a y , callback, init),array i n i t ) 函 数 , − 此 函 数 会 对 a r r a y 中 的 每 个 值 应 用 callback函数处理, init., i n i t 则 为 初 始 值 . − 在 示 例 中 , array是中间件列表, callbackcallback, c a l l b a c k 是 c a l l b a c k 返 回 的 匿 名 函 数 , init是init返回的匿名函数.
- callback会找到当前值指向类的handle方法,把handle方法封装到一个匿名函数并返回,
- 下一个值指向类的handle方法会获取上一个返回的匿名函数,并调用.
- 不过这个调用堆栈和处理过程是相反的,所以在then方法中会使用array_reverse方法倒置中间件列表,这样会形成一个调用堆栈.
- 并且init返回的匿名函数也会在最后被调用,我们把处理请求的逻辑放到init方法中,就会达到先顺序调用中间件,最后处理请求的目的.

      //经过处理后的调用堆栈类似下面的示例
      $init = function () {
          var_dump('init');
          return true;
      };

      $m3 = function () use ($init) {
          var_dump('m3');
          return $init();
      };

      $m2 = function () use ($m3) {
          var_dump('m2');
          return $m3();
      };

      $m1 = function () use ($m2) {
          var_dump('m1');
          return $m2();
      };

      $m1();
abstract class MiddleWare
{
    abstract public function handle($request, $next);
}

class MiddleWareOne extends MiddleWare
{
    public function handle($request, $next)
    {
        var_dump('Handle:中间件---1');
        return $next($request);
    }

    public function process($request, $next)
    {
        var_dump('Process:中间件---1');
        return $next($request);
    }
}

class MiddleWareTwo extends MiddleWare
{
    public function handle($request, $next)
    {
        var_dump('Handle:中间件---2');
        return $next($request);
    }

    public function process($request, $next)
    {
        var_dump('Process:中间件---2');
        return $next($request);
    }
}

class MiddleWareThree extends MiddleWare
{
    public function handle($request, $next)
    {
        var_dump('Handle:中间件---3');
        return $next($request);
    }

    public function process($request, $next)
    {
        var_dump('Process:中间件---3');
        return $next($request);
    }
}

class PipeLine
{
    private $request = null;
    private $pipes = [];
    private $method = 'handle';

    public function send($request)
    {
        $this->request = $request;
        return $this;
    }

    public function through($pipes)
    {
        $this->pipes = $pipes;

        return $this;
    }

    public function via($method)
    {
        $this->method = $method;
        return $this;
    }

    public function then(Closure $closure)
    {
        $pipeline = array_reduce(
            array_reverse($this->pipes), $this->callback(), $this->init($closure)
        );

        return $pipeline($this->request);
    }

    public function callback()
    {
        return function ($stack, $pipe) {
            return function ($request) use ($stack, $pipe) {
                $object = new $pipe();
                return $object->{$this->method}($request, $stack);
            };
        };
    }

    public function init(Closure $closure)
    {
        return function ($request) use ($closure) {
            return $closure($request);
        };
    }
}

class Request
{
    public function run()
    {
        var_dump('处理请求...');
        return true;
    }
}

class Kernel
{
    public $middleware = [
        'MiddleWareOne',
        'MiddleWareTwo',
        'MiddleWareThree'
    ];

    public function run()
    {
        $request = new Request();

        return (new PipeLine())
            ->send($request)
            ->through($this->middleware)
            ->then($this->routeDispatch());
    }

    public function run1()
    {
        $request = new Request();

        return (new PipeLine())
            ->send($request)
            ->through($this->middleware)
            ->via('process')
            ->then($this->routeDispatch());
    }

    public function routeDispatch()
    {
        return function (Request $request) {
            return $request->run();
        };
    }
}

$kernel = new Kernel();

echo '<pre>';
$kernel->run();

echo '<hr>';
$kernel->run1();

echo '<hr>';
$init = function () {
    var_dump('init');
    return true;
};

$m3 = function () use ($init) {
    var_dump('m3');
    return $init();
};

$m2 = function () use ($m3) {
    var_dump('m2');
    return $m3();
};

$m1 = function () use ($m2) {
    var_dump('m1');
    return $m2();
};

$m1();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值