详细分析think中间件的执行顺序

浏览:2929 发布日期:2018/04/05 分类:ThinkPHP5专区 关键字: 中间件
think的中间件执行主要有middlerware的resolve()负责。
这里主要分析resolve()理解think中间件的执行顺序protected function resolve()
{
    return function (Request $request) {
        $middleware = array_shift($this->queue);

        if (null === $middleware) {
            throw new InvalidArgumentException('The queue was exhausted, with no response returned');
        }

        list($call, $param) = $middleware;

        try {
            $response = call_user_func_array($call, [$request, $this->resolve(), $param]);
        } catch (HttpResponseException $exception) {
            $response = $exception->getResponse();
        }

        if (!$response instanceof Response) {
            throw new LogicException('The middleware must return Response instance');
        }

        return $response;
    };
}
这里的resolve()方法将返回一个待调用的中间件闭包

多个中间件的执行顺序主要执行逻辑在$response = call_user_func_array($call, [$request, $this->resolve(), $param]);第二个参数$this->resolve()将获取下个待调用的中间件闭包
这样将注册的中间件队列queue中的所有中间件组织为一个待调用中间件闭包洋葱式结构

执行的时候 则从第一层中间件开始执行,然后调用下层中间件,然后调用下下个中间,直到最后一层中间件
接着从最后一层中间件开始返回到上一层中间件,然后再返回到上上层中间件,
最后返回到第一层中间件    ---->before   ---->   before  ---->  before   --------->  
                                                                                           |
      Middleware1      Middleware2     Middleware3    Controller:action
                                                                                   |
    <----after    <----     after  <----      after   <---------                      
下面写个简单的测试例子
1 生成中间件m1 m2 m3php think make:middleware m1
php think make:middleware m2
php think make:middleware m3
2 中间件中添加输出信息;m1 中间件
<?php

namespace app\http\middleware;

class m1
{
    public function handle($request, \Closure $next)
    {
        $class = __CLASS__;

        // 前置执行逻辑
        echo "我在".$class."前置行为中<br>";
        
        $response =  $next($request);
        
        //后置执行 后置执行逻辑
        echo "我在".$class."后置行为中<br>";
        
        return $response;    
    }
}
;m2中间件
<?php

namespace app\http\middleware;

class m2
{
    public function handle($request, \Closure $next)
    {
        $class = __CLASS__;

        // 前置执行逻辑
        echo "我在".$class."前置行为中<br>";
        
        $response =  $next($request);
        
        //后置执行 后置执行逻辑
        echo "我在".$class."后置行为中<br>";
        
        return $response;    
    }
}
;m3中间件
<?php

namespace app\http\middleware;

class m3
{
    public function handle($request, \Closure $next)
    {
        $class = __CLASS__;

        // 前置执行逻辑
        echo "我在".$class."前置行为中<br>";
        
        $response =  $next($request);
        
        //后置执行 后置执行逻辑
        echo "我在".$class."后置行为中<br>";
        
        return $response;    
    }
}
;index控制器
<?php
namespace app\index\controller;

class Index
{
    public function index()
    {    
        echo "我在控制器".__CLASS__."的方法".__METHOD__."方法中<br>";
    }

    public function hello($name = 'ThinkPHP5')
    {
        return 'hello,' . $name;
    }
}
3 添加中间件;app\middleware.php
<?php

return [
    'm1',
    'm2',
    'm3',
];
3 执行结果我在app\http\middleware\m1前置行为中
我在app\http\middleware\m2前置行为中
我在app\http\middleware\m3前置行为中
我在控制器app\index\controller\Index的方法app\index\controller\Index::index中
我在app\http\middleware\m3后置行为中
我在app\http\middleware\m2后置行为中
我在app\http\middleware\m1后置行为中
中间件的用途

可以用来在控制器的操作执行前的前置行为中进行相关的权限检测Auth
如果不符合权限,则直接return返回上层,不执行控制器的的操作

可以用来在控制器的操作执行完的后置行为中进行相关的逻辑回调


具体就是将上面中间件的echo语句换成对应的处理流程。

think中间的详细实现具体见 https://www.kancloud.cn/zmwtp/thinkphp/577076
最佳答案
评论( 相关
后面还有条评论,点击查看>>