带有请求的苗条传递属性

Slim pass attribute with request

我正在用 slim framework 创建一个简单的 api 。

我想创建一个中间件来检查传递给应用程序的令牌是否有效且未过期。

这是中间件:

public function __invoke(Request $request, Response $response, $next)
{
    $token = $request->getParam('token', null);
    if (is_null($token)) {
        throw new NoTokenException();
    }

    /** @var Auth $authModule */
    $authModule = $this->getContainer()->get('AuthModule');
    $tokenModel = $authModule->validateToken($token);

    $request = $request->withAttribute('user_token_data', $tokenModel->getAttributes());

    return $next($request, $response);
}

这很简单。我验证令牌并将新属性添加到 $request 参数。

在我的路线中,我做了以下事情:

$app->post('/test', function($request, $response, $args){

    /** @var \Controller\TestController $testController */
    $testController = $this->get('TestController');

    $testController->testFunction();


})->add(new \Middleware\Test\SomeOtheroMiddleware($app->getContainer()))
  ->add(new \Middleware\AuthMiddleware($app->getContainer()));

如果我这样做,在路由回调中 $request->getAttribute('user_token_data') 一切就绪。

但是因为我的控制器加载了 slim 容器,所以我想传递 __constructor()

中的 $request 变量

这是我的容器:

$container['TestController'] = function ($container) {
    $testModule = $container->get('TestModule');
    $request = $container->get('request');
    return new \Controller\TestController($testModule, $container, $request);
};

一切都在加载,没有错误,但是在我的 TestController->testFunction() 中,当我尝试访问随容器传递过来的 $request 变量时,我没有 user_token_data键。

我可以为控制器创建一个 setter 来更改路线中的 $request,但这听起来不是个好主意。

我想知道为什么容器中的 $request 不是同一个实例。如果没有 setter.

我怎么能做到这一点

如有任何帮助,我们将不胜感激。

我认为更好的方法是通过直接路由到控制器来使用 Slim。

例如:

class TestController {
    function routeA($request, $response) {
        $tokenData = $request->getAttribute('user_token_data');
        // Your logic here
        // in the end, return the response
        // for example: return $response->withJson(['test' => $tokenData]);
    }
}

然后在您的路线中,使用以下内容:

$app->post('/routeA', ['TestController', 'routeA'])->add(new \Middleware\Test\SomeOtheroMiddleware($app->getContainer()))
  ->add(new \Middleware\AuthMiddleware($app->getContainer()));

这将导致对 /routeA 的任何 POST 请求直接传递给 TestController 中的 routeA 函数以及 $request$response 会被 Slim 注入。

这将使您的代码更好地组织并减少与容器的耦合。

为什么容器里的$request不一样,那是因为容器里有原来的$request,是Slim解析出来的,经过中间件后,不会在容器中更新,因为 $request 对象是不可变的,所以它只是从一个中间件传递到另一个中间件和你的路由,所以容器不知道任何变化。