为侧项目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;
}
}