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

时间:2017-07-18 14:28:05

标签: php middleware

为侧项目API实现中间件,但中间件未按正确顺序调用。应该打印正确的顺序: AUTH [ControllerMethod] TOKEN

但目前它首先打印TOKEN中间件,其结果是: AUTH TOKEN [ControllerMethod]

我无法弄清楚为什么首先调用TokenMiddleware句柄函数。

更新:我们已将问题缩小到Router :: dispatch()方法。出于某种原因,call_user_func_array在我的TokenMiddleware类之前执行。

代码如下:

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);
    };
}

Pipeline.php

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]);
        };
    }
}

Router.php

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']);
        }
    }
}

AuthMiddleware.php

class AuthMiddleware
{
    public function handle($request, Closure $next)
    {
        echo "AUTH";

        return $next($request);
    }
}

TokenMiddleware.php

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

        echo "TOKEN";

        return $response;
    }
}

0 个答案:

没有答案