未按正确顺序调用PHP中间件
为一个side项目API实现中间件,但中间件的调用顺序不正确。正确的顺序应打印: 认证 [控制器方法] 代币 但目前它正在首先打印令牌中间件,结果是: 认证 代币 [控制器方法] 我不明白为什么首先调用TokenHandle函数 更新:我们已经将问题缩小到Router::dispatch()方法。出于某种原因,call_user_func_数组在我的令牌中间件类执行之前执行 代码如下: Kernel.php未按正确顺序调用PHP中间件,php,middleware,Php,Middleware,为一个side项目API实现中间件,但中间件的调用顺序不正确。正确的顺序应打印: 认证 [控制器方法] 代币 但目前它正在首先打印令牌中间件,结果是: 认证 代币 [控制器方法] 我不明白为什么首先调用TokenHandle函数 更新:我们已经将问题缩小到Router::dispatch()方法。出于某种原因,call_user_func_数组在我的令牌中间件类执行之前执行 代码如下: Kernel.php public function handle($request) { if ($
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位,直到得到可再现的错误。当您定位问题时,您可以修复它。否则你就是在追鬼。