未按正确顺序调用PHP中间件

未按正确顺序调用PHP中间件,php,middleware,Php,Middleware,为一个side项目API实现中间件,但中间件的调用顺序不正确。正确的顺序应打印: 认证 [控制器方法] 代币 但目前它正在首先打印令牌中间件,结果是: 认证 代币 [控制器方法] 我不明白为什么首先调用TokenHandle函数 更新:我们已经将问题缩小到Router::dispatch()方法。出于某种原因,call_user_func_数组在我的令牌中间件类执行之前执行 代码如下: Kernel.php public function handle($request) { if ($

为一个side项目API实现中间件,但中间件的调用顺序不正确。正确的顺序应打印: 认证 [控制器方法] 代币

但目前它正在首先打印令牌中间件,结果是: 认证 代币 [控制器方法]

我不明白为什么首先调用TokenHandle函数

更新:我们已经将问题缩小到Router::dispatch()方法。出于某种原因,call_user_func_数组在我的令牌中间件类执行之前执行

代码如下:

Kernel.php

public function handle($request)
{
    if ($routePackage = $this->router->find($request)) {
        $controller_name = $routePackage['route']->action['controller'];
        $controller = $this->controllerCollection->find($controller_name);

        if ($controller === null) {
            $fqcn = "\\app\\controllers\\".$controller_name;
            $controller = new $fqcn();
            $this->controllerCollection->add($controller_name, $controller);
        }

        return (new Pipeline)
                ->send($request)
                ->through($controller->getMiddleware())
                ->then($this->dispatchToRouter());
    }
}

private function dispatchToRouter()
{
    return function ($request)
    {
        return $this->router->dispatch($request);
    };
}
class Pipeline
{
    private $pipes = [];

    private $object;

    private $method = 'handle';

    public function send($object)
    {
        $this->object = $object;

        return $this;
    }

    public function through($pipes)
    {
        $this->pipes = array_merge($this->pipes, $pipes); 
        return $this;
    }

    public function then(Closure $core)
    {
        $coreFunction = $this->createCoreFunction($core);

        $pipes = array_reverse($this->pipes);

        $completePipeline = array_reduce($pipes, function($nextPipe, $pipe)
        {
            return $this->createPipe($nextPipe, $pipe);
        }, $coreFunction);

        return $completePipeline();
    }

    private function createCoreFunction(Closure $core)
    {
        return function() use ($core)
        {
            return call_user_func($core, $this->object);
        };
    }

    private function createPipe($nextPipe, $pipe)
    {
        #print_r($nextPipe);
        #echo "==============================================";
        #print_r($pipe);
        return function () use ($nextPipe, $pipe)
        {
            return call_user_func_array([$pipe, $this->method], [$this->object, $nextPipe]);
        };
    }
}
class Router
{
    private $controllerCollection;

    public function __construct($controllerCollection = null)
    {
        $this->controllerCollection = $controllerCollection;
        $this->routeCollection = new RouteCollection();
    }

    public function find($request)
    {
        return $this->routeCollection->find($request);
    }

    public function dispatch($request)
    {
        print_r($request);
        if ($routePackage = $this->find($request)) {
            $controller_name = $routePackage['route']->action['controller'];
            $controller = $this->controllerCollection->find($controller_name);

            // Inject request if needed -- TODO: MOVE THIS
           # $reflection_method = new \ReflectionMethod($controller, $routePackage['route']->action['method']);
            #$args = $reflection_method->getParameters();

           # for ($i = 0; $i < count($args); $i++) {
            #    $class = $args[$i]->getClass();

            #    if ($class) {
            #        if ($class->getName() === 'framework\http\Request') {
             #           if ($routePackage['params']) {
             #               array_splice($routePackage['params'], $i, 0, array($request));   
             #           } else {
                            $routePackage['params'] = [$request];
            #            }

            #            break;
            #        }
            #    }     
            #}

            return call_user_func_array([$controller, $routePackage['route']->action['method']], $routePackage['params']);  // PROBLEM LIES HERE: THIS IS BEING CALLED BEFORE MIDDLEWARE
            #return $controller->call($routePackage['route']->action['method'], $routePackage['params']);
        }
    }
}
class AuthMiddleware
{
    public function handle($request, Closure $next)
    {
        echo "AUTH";

        return $next($request);
    }
}
class TokenMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        echo "TOKEN";

        return $response;
    }
}
Pipeline.php

public function handle($request)
{
    if ($routePackage = $this->router->find($request)) {
        $controller_name = $routePackage['route']->action['controller'];
        $controller = $this->controllerCollection->find($controller_name);

        if ($controller === null) {
            $fqcn = "\\app\\controllers\\".$controller_name;
            $controller = new $fqcn();
            $this->controllerCollection->add($controller_name, $controller);
        }

        return (new Pipeline)
                ->send($request)
                ->through($controller->getMiddleware())
                ->then($this->dispatchToRouter());
    }
}

private function dispatchToRouter()
{
    return function ($request)
    {
        return $this->router->dispatch($request);
    };
}
class Pipeline
{
    private $pipes = [];

    private $object;

    private $method = 'handle';

    public function send($object)
    {
        $this->object = $object;

        return $this;
    }

    public function through($pipes)
    {
        $this->pipes = array_merge($this->pipes, $pipes); 
        return $this;
    }

    public function then(Closure $core)
    {
        $coreFunction = $this->createCoreFunction($core);

        $pipes = array_reverse($this->pipes);

        $completePipeline = array_reduce($pipes, function($nextPipe, $pipe)
        {
            return $this->createPipe($nextPipe, $pipe);
        }, $coreFunction);

        return $completePipeline();
    }

    private function createCoreFunction(Closure $core)
    {
        return function() use ($core)
        {
            return call_user_func($core, $this->object);
        };
    }

    private function createPipe($nextPipe, $pipe)
    {
        #print_r($nextPipe);
        #echo "==============================================";
        #print_r($pipe);
        return function () use ($nextPipe, $pipe)
        {
            return call_user_func_array([$pipe, $this->method], [$this->object, $nextPipe]);
        };
    }
}
class Router
{
    private $controllerCollection;

    public function __construct($controllerCollection = null)
    {
        $this->controllerCollection = $controllerCollection;
        $this->routeCollection = new RouteCollection();
    }

    public function find($request)
    {
        return $this->routeCollection->find($request);
    }

    public function dispatch($request)
    {
        print_r($request);
        if ($routePackage = $this->find($request)) {
            $controller_name = $routePackage['route']->action['controller'];
            $controller = $this->controllerCollection->find($controller_name);

            // Inject request if needed -- TODO: MOVE THIS
           # $reflection_method = new \ReflectionMethod($controller, $routePackage['route']->action['method']);
            #$args = $reflection_method->getParameters();

           # for ($i = 0; $i < count($args); $i++) {
            #    $class = $args[$i]->getClass();

            #    if ($class) {
            #        if ($class->getName() === 'framework\http\Request') {
             #           if ($routePackage['params']) {
             #               array_splice($routePackage['params'], $i, 0, array($request));   
             #           } else {
                            $routePackage['params'] = [$request];
            #            }

            #            break;
            #        }
            #    }     
            #}

            return call_user_func_array([$controller, $routePackage['route']->action['method']], $routePackage['params']);  // PROBLEM LIES HERE: THIS IS BEING CALLED BEFORE MIDDLEWARE
            #return $controller->call($routePackage['route']->action['method'], $routePackage['params']);
        }
    }
}
class AuthMiddleware
{
    public function handle($request, Closure $next)
    {
        echo "AUTH";

        return $next($request);
    }
}
class TokenMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        echo "TOKEN";

        return $response;
    }
}
Router.php

public function handle($request)
{
    if ($routePackage = $this->router->find($request)) {
        $controller_name = $routePackage['route']->action['controller'];
        $controller = $this->controllerCollection->find($controller_name);

        if ($controller === null) {
            $fqcn = "\\app\\controllers\\".$controller_name;
            $controller = new $fqcn();
            $this->controllerCollection->add($controller_name, $controller);
        }

        return (new Pipeline)
                ->send($request)
                ->through($controller->getMiddleware())
                ->then($this->dispatchToRouter());
    }
}

private function dispatchToRouter()
{
    return function ($request)
    {
        return $this->router->dispatch($request);
    };
}
class Pipeline
{
    private $pipes = [];

    private $object;

    private $method = 'handle';

    public function send($object)
    {
        $this->object = $object;

        return $this;
    }

    public function through($pipes)
    {
        $this->pipes = array_merge($this->pipes, $pipes); 
        return $this;
    }

    public function then(Closure $core)
    {
        $coreFunction = $this->createCoreFunction($core);

        $pipes = array_reverse($this->pipes);

        $completePipeline = array_reduce($pipes, function($nextPipe, $pipe)
        {
            return $this->createPipe($nextPipe, $pipe);
        }, $coreFunction);

        return $completePipeline();
    }

    private function createCoreFunction(Closure $core)
    {
        return function() use ($core)
        {
            return call_user_func($core, $this->object);
        };
    }

    private function createPipe($nextPipe, $pipe)
    {
        #print_r($nextPipe);
        #echo "==============================================";
        #print_r($pipe);
        return function () use ($nextPipe, $pipe)
        {
            return call_user_func_array([$pipe, $this->method], [$this->object, $nextPipe]);
        };
    }
}
class Router
{
    private $controllerCollection;

    public function __construct($controllerCollection = null)
    {
        $this->controllerCollection = $controllerCollection;
        $this->routeCollection = new RouteCollection();
    }

    public function find($request)
    {
        return $this->routeCollection->find($request);
    }

    public function dispatch($request)
    {
        print_r($request);
        if ($routePackage = $this->find($request)) {
            $controller_name = $routePackage['route']->action['controller'];
            $controller = $this->controllerCollection->find($controller_name);

            // Inject request if needed -- TODO: MOVE THIS
           # $reflection_method = new \ReflectionMethod($controller, $routePackage['route']->action['method']);
            #$args = $reflection_method->getParameters();

           # for ($i = 0; $i < count($args); $i++) {
            #    $class = $args[$i]->getClass();

            #    if ($class) {
            #        if ($class->getName() === 'framework\http\Request') {
             #           if ($routePackage['params']) {
             #               array_splice($routePackage['params'], $i, 0, array($request));   
             #           } else {
                            $routePackage['params'] = [$request];
            #            }

            #            break;
            #        }
            #    }     
            #}

            return call_user_func_array([$controller, $routePackage['route']->action['method']], $routePackage['params']);  // PROBLEM LIES HERE: THIS IS BEING CALLED BEFORE MIDDLEWARE
            #return $controller->call($routePackage['route']->action['method'], $routePackage['params']);
        }
    }
}
class AuthMiddleware
{
    public function handle($request, Closure $next)
    {
        echo "AUTH";

        return $next($request);
    }
}
class TokenMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        echo "TOKEN";

        return $response;
    }
}
TokenMiddleware.php

public function handle($request)
{
    if ($routePackage = $this->router->find($request)) {
        $controller_name = $routePackage['route']->action['controller'];
        $controller = $this->controllerCollection->find($controller_name);

        if ($controller === null) {
            $fqcn = "\\app\\controllers\\".$controller_name;
            $controller = new $fqcn();
            $this->controllerCollection->add($controller_name, $controller);
        }

        return (new Pipeline)
                ->send($request)
                ->through($controller->getMiddleware())
                ->then($this->dispatchToRouter());
    }
}

private function dispatchToRouter()
{
    return function ($request)
    {
        return $this->router->dispatch($request);
    };
}
class Pipeline
{
    private $pipes = [];

    private $object;

    private $method = 'handle';

    public function send($object)
    {
        $this->object = $object;

        return $this;
    }

    public function through($pipes)
    {
        $this->pipes = array_merge($this->pipes, $pipes); 
        return $this;
    }

    public function then(Closure $core)
    {
        $coreFunction = $this->createCoreFunction($core);

        $pipes = array_reverse($this->pipes);

        $completePipeline = array_reduce($pipes, function($nextPipe, $pipe)
        {
            return $this->createPipe($nextPipe, $pipe);
        }, $coreFunction);

        return $completePipeline();
    }

    private function createCoreFunction(Closure $core)
    {
        return function() use ($core)
        {
            return call_user_func($core, $this->object);
        };
    }

    private function createPipe($nextPipe, $pipe)
    {
        #print_r($nextPipe);
        #echo "==============================================";
        #print_r($pipe);
        return function () use ($nextPipe, $pipe)
        {
            return call_user_func_array([$pipe, $this->method], [$this->object, $nextPipe]);
        };
    }
}
class Router
{
    private $controllerCollection;

    public function __construct($controllerCollection = null)
    {
        $this->controllerCollection = $controllerCollection;
        $this->routeCollection = new RouteCollection();
    }

    public function find($request)
    {
        return $this->routeCollection->find($request);
    }

    public function dispatch($request)
    {
        print_r($request);
        if ($routePackage = $this->find($request)) {
            $controller_name = $routePackage['route']->action['controller'];
            $controller = $this->controllerCollection->find($controller_name);

            // Inject request if needed -- TODO: MOVE THIS
           # $reflection_method = new \ReflectionMethod($controller, $routePackage['route']->action['method']);
            #$args = $reflection_method->getParameters();

           # for ($i = 0; $i < count($args); $i++) {
            #    $class = $args[$i]->getClass();

            #    if ($class) {
            #        if ($class->getName() === 'framework\http\Request') {
             #           if ($routePackage['params']) {
             #               array_splice($routePackage['params'], $i, 0, array($request));   
             #           } else {
                            $routePackage['params'] = [$request];
            #            }

            #            break;
            #        }
            #    }     
            #}

            return call_user_func_array([$controller, $routePackage['route']->action['method']], $routePackage['params']);  // PROBLEM LIES HERE: THIS IS BEING CALLED BEFORE MIDDLEWARE
            #return $controller->call($routePackage['route']->action['method'], $routePackage['params']);
        }
    }
}
class AuthMiddleware
{
    public function handle($request, Closure $next)
    {
        echo "AUTH";

        return $next($request);
    }
}
class TokenMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        echo "TOKEN";

        return $response;
    }
}

你忘了展示你是如何注册这些中间产品的。顺序由
$this->pipes=array\u merge($this->pipes,$pipes)
$pipes=array\u reverse($this->pipes)定义嗯,我认为这不重要。我会在可能的时候发布代码。它们被添加到控制器的构造函数中。这个实现类似于Laravel,因此,应该由中间件如何处理下一个闭包来决定。请参阅我的AuthMiddleware和TokenMiddleware处理方法,并注意其中的区别。啊,事实上,我没有注意到令牌是在控制器之后执行的。你是说如果你死在auth中间件中,令牌中间件仍然会呼应“令牌”?@AlexBlex,我还没有理解这个逻辑。如果您在身份验证中失败,您将最终死亡,并且不会进一步执行。然而,现在,我只是尝试以正确的顺序输出,以确保方法/闭包以正确的顺序被调用:它们不是。你确定吗?这里没有对不起,伙计,在Stackoverflow上调试是一条没有出路的路。试着自己做同样的事情-一次添加1位,直到得到可再现的错误。当您定位问题时,您可以修复它。否则你就是在追鬼。