我已经从PHP-FIG(HTTP服务器请求处理程序)读取了PSR-15,并想知道何时调用某个操作(控制器操作或关闭)。
在处理所有中间件时,应在传递所有中间件后调用该操作。在操作之后,所有中间件再次从内部传递到外部(如Slim Framework中的User Guide所述)。
我在GitHub上从Laravel浏览了代码,但无法弄清楚,他们如何调用该操作然后再次遍历所有中间件。
这个answer告诉我,Slim将自己添加到中间件堆栈中。我猜,然后以某种方式执行动作。但是Slim正在使用双通。
中间件堆栈和执行如何通过单次传递(如PSR-15中所述)并调用所有中间件之间的操作?
答案 0 :(得分:1)
我实际上开始将控制器添加为中间件。为此,RequestHandler必须能够接受要添加的新中间件。我的路由器负责分配适当的中间件。这样,我也可以为每条路线分配多个操作。
答案 1 :(得分:0)
这是一个示例代码,我可以想象它可以工作。当然,缺少很多东西,例如设置路由,解决依赖关系,PSR接口以及框架随附的其他东西。
此代码将中间件和操作添加到请求处理程序中,并且请求处理程序可以在需要时执行两者。
<?php
interface RequestInterface {}
class Request implements RequestInterface {}
interface ResponseInterface {}
class Response implements ResponseInterface {}
class Response404 implements ResponseInterface {}
class FirstMiddleware {
public function process(RequestInterface $request, RequestHandler $handler): ResponseInterface {
echo ' First-Before ';
$response = $handler->handle($request);
echo ' First-After ';
return $response;
}
}
class SecondMiddleware {
public function process(Request $request, RequestHandler $handler): Response {
echo ' Second-Before ';
$response = $handler->handle($request);
echo ' Second-After ';
return $response;
}
}
class RequestHandler {
private $middleware;
private $callable;
private $params;
public function __construct(array $middleware = [], callable $callable, array $params = []) {
$this->middleware = $middleware;
$this->callable = $callable;
$this->params = $params;
}
public function handle(RequestInterface $request): ResponseInterface {
$middleware = current($this->middleware);
next($this->middleware);
if (!$middleware) {
$response = ($this->callable)(...$this->params);
return $response;
}
return $middleware->process($request, $this);
}
}
class App {
private $middleware = [];
private $callable;
public function setMiddleware(array $middleware) {
$this->middleware = $middleware;
}
public function setCallable(callable $callable) {
$this->callable = $callable;
}
public function run() {
$handler = new RequestHandler($this->middleware, $this->callable, ['one', 'two']);
$handler->handle(new Request());
}
}
class Controller {
public function action($a, $b) {
echo ' Controller Action ';
echo $a;
echo $b;
return new Response();
}
}
$middleware = [
new FirstMiddleware(),
new SecondMiddleware(),
];
// Using closure ...
$callable = function ($a, $b) {
echo ' Closure Action ';
echo $a;
echo $b;
return new Response();
};
// Or an object method
$controller = new Controller();
$callable = array($controller, 'action');
/** Run */
$app = new App();
$app->setMiddleware($middleware);
$app->setCallable($callable);
$app->run();