Slim 3 在中间件中获取当前路由
Slim 3 get current route in middleware
我想在中间件class中获取当前I路由的名称。以前(在 Slim 2.* 中)你可以像这样获取当前路由:
$route = $this->app->router->getCurrentRoute();
但是这个功能在Slim的3.0版本中已经被移除了。我在 Slim\App
的 __invoke
方法中找到了以下代码:
// Get the route info
$routeInfo = $request->getAttribute('routeInfo');
/** @var \Slim\Interfaces\RouterInterface $router */
$router = $this->container->get('router');
// If router hasn't been dispatched or the URI changed then dispatch
if (null === $routeInfo || ($routeInfo['request'] !== [$request->getMethod(), (string) $request->getUri()])) {
$request = $this->dispatchRouterAndPrepareRoute($request, $router);
$routeInfo = $request->getAttribute('routeInfo');
}
这表示当前路由作为属性routeInfo
存储在Request
中。但似乎我的自定义中间件 class 在设置属性之前被调用(通过 $this->dispatchRouterAndPrepareRoute($request, $router);
方法)。因为调用 $request->getAttribute('routeInfo')
解析为 NULL
.
所以我的问题是;如何从中间件 function/class?
获取当前路由(或路由名称)
或者我应该从 Slim\App
复制上面的代码吗?
以下是否为您提供了所需的足够信息,或者您是否还需要 routeInfo 中的 'request' 位?
$app->getContainer()->get('router')->dispatch($req);
如果您还需要 'request' 位,那么您将需要手动执行与 dispatchRouterAndPrepareRoute
相同的操作。
if ($routeInfo[0] === Dispatcher::FOUND) {
$routeArguments = [];
foreach ($routeInfo[2] as $k => $v) {
$routeArguments[$k] = urldecode($v);
}
$route = $router->lookupRoute($routeInfo[1]);
$route->prepare($request, $routeArguments);
// add route to the request's attributes in case a middleware or handler needs access to the route
$request = $request->withAttribute('route', $route);
}
$routeInfo['request'] = [$request->getMethod(), (string) $request->getUri()];
希望对您有所帮助。
显然,您可以使用以下设置配置 Slim 以在进入中间件之前确定路由:
$app = new Slim\App([
'settings' => [
'determineRouteBeforeAppMiddleware' => true,
]
]);
我不确定这会产生什么样的影响,但它对我有用:)
以下是在 Slim 框架 3 的中间件中获取当前路由的方法:
$routeInfo = $request->getAttribute('routeInfo');
请注意,您应该在中间件的 __invoke()
函数中使用它。这是示例用法:
public function __invoke($request, $response, $next)
{
....
$routeInfo = $request->getAttribute('routeInfo');
....
}
$routeInfo 应包含如下对象:
{
"0": 1,
"1": "route6",
"2": {
"name": "loremipsum"
},
"request": [
"POST",
"http://example.org/loremipsum"
]
}
对于 Slim3,这里有一个例子向您展示如何从中间件中获取路由信息,这实际上是前面答案的组合。
<?php
$slimSettings = array('determineRouteBeforeAppMiddleware' => true);
// This is not necessary for this answer, but very useful
if (ENVIRONMENT == "dev")
{
$slimSettings['displayErrorDetails'] = true;
}
$slimConfig = array('settings' => $slimSettings);
$app = new \Slim\App($slimConfig);
$myMiddleware = function ($request, $response, $next) {
$route = $request->getAttribute('route');
$routeName = $route->getName();
$groups = $route->getGroups();
$methods = $route->getMethods();
$arguments = $route->getArguments();
print "Route Info: " . print_r($route, true);
print "Route Name: " . print_r($routeName, true);
print "Route Groups: " . print_r($groups, true);
print "Route Methods: " . print_r($methods, true);
print "Route Arguments: " . print_r($arguments, true);
};
// Define app routes
$app->add($myMiddleware);
$app->get('/', function (\Slim\Http\Request $request, Slim\Http\Response $response, $args) {
# put some code here....
})
在我的例子中,我想添加中间件来确保用户在某些路由上登录,如果没有,则将他们重定向到登录页面。我发现最简单的方法是在这样的路线上使用 ->setName()
:
$app->get('/', function (\Slim\Http\Request $request, Slim\Http\Response $response, $args) {
return $response->withRedirect('/home');
})->setName('index');
那么如果这条路由被匹配,中间件示例中的$routeName
将是"index"
。然后我定义了不需要身份验证的路由数组列表,并检查当前路由是否在该列表中。例如。
if (!in_array($routeName, $publicRoutesArray))
{
# @TODO - check user logged in and redirect if not.
}
$request->getUri()->getPath()
获取当前路线,即使在 middleware
。
我想在中间件class中获取当前I路由的名称。以前(在 Slim 2.* 中)你可以像这样获取当前路由:
$route = $this->app->router->getCurrentRoute();
但是这个功能在Slim的3.0版本中已经被移除了。我在 Slim\App
的 __invoke
方法中找到了以下代码:
// Get the route info
$routeInfo = $request->getAttribute('routeInfo');
/** @var \Slim\Interfaces\RouterInterface $router */
$router = $this->container->get('router');
// If router hasn't been dispatched or the URI changed then dispatch
if (null === $routeInfo || ($routeInfo['request'] !== [$request->getMethod(), (string) $request->getUri()])) {
$request = $this->dispatchRouterAndPrepareRoute($request, $router);
$routeInfo = $request->getAttribute('routeInfo');
}
这表示当前路由作为属性routeInfo
存储在Request
中。但似乎我的自定义中间件 class 在设置属性之前被调用(通过 $this->dispatchRouterAndPrepareRoute($request, $router);
方法)。因为调用 $request->getAttribute('routeInfo')
解析为 NULL
.
所以我的问题是;如何从中间件 function/class?
获取当前路由(或路由名称)或者我应该从 Slim\App
复制上面的代码吗?
以下是否为您提供了所需的足够信息,或者您是否还需要 routeInfo 中的 'request' 位?
$app->getContainer()->get('router')->dispatch($req);
如果您还需要 'request' 位,那么您将需要手动执行与 dispatchRouterAndPrepareRoute
相同的操作。
if ($routeInfo[0] === Dispatcher::FOUND) {
$routeArguments = [];
foreach ($routeInfo[2] as $k => $v) {
$routeArguments[$k] = urldecode($v);
}
$route = $router->lookupRoute($routeInfo[1]);
$route->prepare($request, $routeArguments);
// add route to the request's attributes in case a middleware or handler needs access to the route
$request = $request->withAttribute('route', $route);
}
$routeInfo['request'] = [$request->getMethod(), (string) $request->getUri()];
希望对您有所帮助。
显然,您可以使用以下设置配置 Slim 以在进入中间件之前确定路由:
$app = new Slim\App([
'settings' => [
'determineRouteBeforeAppMiddleware' => true,
]
]);
我不确定这会产生什么样的影响,但它对我有用:)
以下是在 Slim 框架 3 的中间件中获取当前路由的方法:
$routeInfo = $request->getAttribute('routeInfo');
请注意,您应该在中间件的 __invoke()
函数中使用它。这是示例用法:
public function __invoke($request, $response, $next)
{
....
$routeInfo = $request->getAttribute('routeInfo');
....
}
$routeInfo 应包含如下对象:
{
"0": 1,
"1": "route6",
"2": {
"name": "loremipsum"
},
"request": [
"POST",
"http://example.org/loremipsum"
]
}
对于 Slim3,这里有一个例子向您展示如何从中间件中获取路由信息,这实际上是前面答案的组合。
<?php
$slimSettings = array('determineRouteBeforeAppMiddleware' => true);
// This is not necessary for this answer, but very useful
if (ENVIRONMENT == "dev")
{
$slimSettings['displayErrorDetails'] = true;
}
$slimConfig = array('settings' => $slimSettings);
$app = new \Slim\App($slimConfig);
$myMiddleware = function ($request, $response, $next) {
$route = $request->getAttribute('route');
$routeName = $route->getName();
$groups = $route->getGroups();
$methods = $route->getMethods();
$arguments = $route->getArguments();
print "Route Info: " . print_r($route, true);
print "Route Name: " . print_r($routeName, true);
print "Route Groups: " . print_r($groups, true);
print "Route Methods: " . print_r($methods, true);
print "Route Arguments: " . print_r($arguments, true);
};
// Define app routes
$app->add($myMiddleware);
$app->get('/', function (\Slim\Http\Request $request, Slim\Http\Response $response, $args) {
# put some code here....
})
在我的例子中,我想添加中间件来确保用户在某些路由上登录,如果没有,则将他们重定向到登录页面。我发现最简单的方法是在这样的路线上使用 ->setName()
:
$app->get('/', function (\Slim\Http\Request $request, Slim\Http\Response $response, $args) {
return $response->withRedirect('/home');
})->setName('index');
那么如果这条路由被匹配,中间件示例中的$routeName
将是"index"
。然后我定义了不需要身份验证的路由数组列表,并检查当前路由是否在该列表中。例如。
if (!in_array($routeName, $publicRoutesArray))
{
# @TODO - check user logged in and redirect if not.
}
$request->getUri()->getPath()
获取当前路线,即使在 middleware
。