【问题标题】:Slim 3 get current route in middlewareSlim 3 在中间件中获取当前路由
【发布时间】:2016-04-01 07:04:32
【问题描述】:

我想在中间件类中获取当前 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中。但似乎我的自定义中间件类在设置属性之前被调用(通过$this->dispatchRouterAndPrepareRoute($request, $router); 方法)。因为调用$request->getAttribute('routeInfo') 会解析为NULL

所以我的问题是;如何从中间件函数/类中获取当前路由(或路由名称)?

或者我应该从Slim\App复制上面的代码吗?

【问题讨论】:

  • 我也无法在中间件中获取当前路由。我已经设置了'determineRouteBeforeAppMiddleware' => true,当我设置$route = $request->getAttribute('route'); 时,我得到了一个对象(Slim\Route),但是当我设置$routeName = $route->getName(); 时,我得到了空值。有人有什么建议吗?
  • 您是否通过setName() 方法命名了路线? (slimframework.com/docs/objects/router.html#route-names)
  • 谢谢@Wessel。问题是声明路由后缺少setName() 方法。

标签: php slim slim-3


【解决方案1】:
$request->getUri()->getPath()

获取当前路线,即使在middleware

【讨论】:

    【解决方案2】:

    对于 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....
    })
    

    在我的例子中,我想添加中间件,以确保用户在某些路由上登录,如果没有,则将他们重定向到登录页面。我发现最简单的方法是在这样的路线上使用-&gt;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.
    }
    

    【讨论】:

      【解决方案3】:

      以下是在 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"
          ]
        }
      

      【讨论】:

        【解决方案4】:

        显然你可以配置 Slim 在进入中间件之前通过这个设置确定路由:

        $app = new Slim\App([
            'settings'  => [
                'determineRouteBeforeAppMiddleware' => true,
            ]
        ]);
        

        我不确定这会产生什么样的影响,但它对我有用 :)

        【讨论】:

        • 一旦你这样做了,使用@SamarRizvi 答案可以在中间件中使用$routeInfo = $request-&gt;getAttribute('routeInfo');。没有这个,$routeInfo 什么都不是。
        • 这是专门针对 App 中间件的。此外,如果路线 不存在 存在,那么 @SamarRizvi 的答案中 $route 将在此设置更改后为空。
        【解决方案5】:

        以下是否为您提供了所需的足够信息,或者您是否还需要 routeInfo 中的“请求”位?

        $app->getContainer()->get('router')->dispatch($req);
        

        如果您还需要“请求”位,那么您将需要手动执行 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 2.* 方法更复杂。
        猜你喜欢
        • 2015-11-16
        • 1970-01-01
        • 1970-01-01
        • 2016-12-16
        • 2017-10-03
        • 2020-12-30
        • 2021-06-21
        • 2013-12-14
        • 2015-12-25
        相关资源
        最近更新 更多