如何在PSR-15中间件堆栈中调用函数(控制器操作)

时间:2018-03-02 14:03:38

标签: php controller action middleware php-fig

我已经从PHP-FIG(HTTP服务器请求处理程序)读取了PSR-15,并想知道何时调用某个操作(控制器操作或关闭)。

在处理所有中间件时,应在传递所有中间件后调用该操作。在操作之后,所有中间件再次从内部传递到外部(如Slim Framework中的User Guide所述)。

我在GitHub上从Laravel浏览了代码,但无法弄清楚,他们如何调用该操作然后再次遍历所有中间件。

这个answer告诉我,Slim将自己添加到中间件堆栈中。我猜,然后以某种方式执行动作。但是Slim正在使用双通。

中间件堆栈和执行如何通过单次传递(如PSR-15中所述)并调用所有中间件之间的操作?

2 个答案:

答案 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();