我正在使用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')
一切就绪。
但是由于我的控制器加载了苗条容器,我想通过$request
__constructor()
变量
这是我的容器:
$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
不是同一个实例。如果没有制定者,我怎么能这样做。
任何帮助将不胜感激。
答案 0 :(得分:1)
我认为更好的方法是通过直接路由到控制器来使用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()));
这会导致POST
/routeA
的任何routeA
请求直接传递到TestController
$request
以及$response
和$request
中的$request
功能将由Slim注入。
这将使您的代码更有条理,更少与容器结合。
至于为什么$request
在容器中不一样,那是因为容器包含Slim解析的原始["January 27, 5:00PM - 10:00PM", "February 28, 11:00AM - 10:00PM", "March 29, 11:00AM - 9:00PM"]
,一旦它通过中间件,它就不是在容器中更新,因为for index in 0..<array.count
{
if let range = array[index].range(of: ",")
{
date = array[index][array[index].startIndex..<range.lowerBound]
}
}
对象是不可变的,所以它只是从一个中间件传递到另一个中间件和路由,因此容器不知道任何更改。