中间件中的瘦PHP路由


Slim PHP Route in Middleware

在Slim中,是否可以在中间件中获取当前路由?

class Auth extends 'Slim'Middleware{
  public function call(){ 
    $currentRoute = $this->app->getRoute(); // Something like this?
  }
}

我知道你可以在调用slim.before.dispatch钩子后调用$app->router()->getCurrentRoute(),但当你从中间件调用它时,它会返回一个非对象。如有任何帮助,我们将不胜感激。

是和否。如果你查看Slim的源代码,你会发现当调用Slim::run方法时,注册的中间件是按LIFO顺序调用的,然后Slim运行它自己的"调用"方法,开始处理请求。正是在这种方法中,Slim解析并处理了路由。在这种情况下,您无法在Middleware::call方法中访问$app->router()->getCurrentRoute(),因为它还没有被解析和定义。

做到这一点的唯一方法是在中间件中的slim.before.dispatch上注册一个侦听器,并在该方法中实现您想要做的任何事情。

根据类的名称,我假设您正在尝试创建一个基本的身份验证模块?我以前也做过类似的事情,结果是这样的:

class AuthMiddleware extends 'Slim'Middleware
{
    public function call()
    {
        $this->app->hook('slim.before.dispatch', array($this, 'onBeforeDispatch'));
        $this->next->call();
    }
    public function onBeforeDispatch()
    {
        $route = $this->app->router()->getCurrentRoute();
        //Here I check if the route is "protected" some how, and if it is, check the
        //user has permission, if not, throw either 404 or redirect.
        if (is_route_protected() && !user_has_permission())
        {
            $this->app->redirect('/login?return=' . urlencode(filter_input(INPUT_SERVER, 'REQUEST_URI')));
        }
    }
}

在本例中,onBeforeDispatch方法将在调用所有路由处理程序之前运行。如果您查看源代码,您可以看到事件在try/catch块内触发,该块正在侦听$app->redirect()$app->pass()等抛出的异常。这意味着我们可以在这里实现我们的检查/重定向逻辑,就像这是一个路由处理程序函数一样。

上面的is_route_protecteduser_has_permission只是伪代码,用来说明我的身份验证中间件是如何工作的。我构造了这个类,这样你就可以在中间件构造函数中为受保护的路由指定一个路由列表或正则表达式,还可以传递一个实现用户权限检查的服务对象,等等。希望这能有所帮助。

有另一种方法可以做到这一点,因为我也遇到过同样的情况。我想避免的是按路线匹配任何东西,并想使用路线名称,所以你可以尝试以下方法:

public function call() {
    $routeIWantToCheckAgainst = $this->slimApp->router()->urlFor('my.route.name');
    $requestRoute = $this->slimApp->request()->getPathInfo();
    if ($routeIWantToCheckAgainst !== $requestRoute) {
        // Do stuff you need to in here
    }
    $this->next->call();
}

你甚至可以有一组你不想让中间件运行的路由,然后检查它是否在_array()等中,如果不是,就做你需要做的事情。

您应该使用app->request()->getPathInfo()而不是app->getRoute()。

class Auth extends 'Slim'Middleware{
    public function call(){ 
        $currentRoute = $this->app->request()->getPathInfo();
    }
}