Как вызвать функцию (действие контроллера) в стеке промежуточного программного обеспечения PSR-15
Я прочитал PSR-15 из PHP-FIG (обработчик запросов HTTP-сервера) и задаюсь вопросом, когда вызывается действие (действие контроллера или закрытие).
При обработке через все промежуточные программы действие должно вызываться после прохождения всех промежуточных программ. После этого действия все промежуточные программы снова передаются изнутри наружу (как описано в Руководстве пользователя Slim Framework).
Я просматривал код от Laravel на GitHub, но не могу понять, как они вызывают действие, а затем снова пересекают все промежуточные программы.
Этот ответ говорит мне, что Slim добавляет себя в стек промежуточного программного обеспечения. Я думаю, тогда он выполняет действие как-то. Но Слим использует двойной проход.
Как стек промежуточного программного обеспечения и его выполнение выглядят с одним проходом (как описано в PSR-15) и вызывают действие между всеми промежуточными программами?
1 ответ
Вот пример кода, который, как я мог себе представить, может сработать. Конечно, не хватает многих вещей, таких как настройка маршрутов, разрешение зависимостей, интерфейсы 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();
Я начал добавлять контроллеры в качестве промежуточного программного обеспечения. Чтобы это работало, RequestHandler должен иметь возможность принимать новые промежуточные программы для добавления. И мой маршрутизатор выполняет работу по назначению соответствующего промежуточного программного обеспечения. Таким образом, я также могу назначить более одного действия на маршрут.