简体   繁体   English

中间件中的Slim PHP路由

[英]Slim PHP Route in Middleware

In Slim is it possible to get the current route within middleware? 在Slim中,是否可以在中间件中获取当前路由?

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

I know you can call $app->router()->getCurrentRoute() after the slim.before.dispatch hook is called, but when you call this from middleware it returns a non-object. 我知道你可以在调用slim.before.dispatch挂钩后调用$app->router()->getCurrentRoute() ,但是当你从中间件调用它时它会返回一个非对象。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Yes and no. 是的,不是。 If you look at the source code for Slim, you will see that registered Middlewares are called in LIFO order when the Slim::run method is called, and then Slim runs it's own "call" method where the processing of the request begins. 如果你看一下Slim的源代码,你会看到在调用Slim::run方法时以LIFO顺序调用已注册的中间件,然后Slim运行它自己的“call”方法,开始处理请求。 It is in this method that Slim parses and processes the route. 正是在这种方法中,Slim解析并处理路由。 In which case, you cannot access $app->router()->getCurrentRoute() in the Middleware::call method because it won't have been parsed and defined yet. 在这种情况下,您无法在Middleware::call方法中访问$app->router()->getCurrentRoute() ,因为它尚未被解析和定义。

The only way to do this is to register a listener on slim.before.dispatch inside your Middleware, and implement whatever you want to do in that method. 执行此操作的唯一方法是在中间件中的slim.before.dispatch上注册侦听器,并在该方法中实现您想要执行的任何操作。

From the name of your class I assume you are trying to create a basic authentication module? 从你的班级名称我假设你正在尝试创建一个基本的身份验证模块? I've done something similar to this before, and it went something like this: 我之前做过类似的事情,它是这样的:

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')));
        }
    }
}

In this example, the onBeforeDispatch method will be run before of the route handlers are invoked. 在此示例中,将在调用路由处理程序之前运行onBeforeDispatch方法。 If you look at the source code, you can see the events are fired inside a try/catch block that is listening for the exceptions thrown by $app->redirect() and $app->pass() , etc. This means we can implement our check/redirect logic here just as if this was a route handler function. 如果查看源代码,您可以看到在侦听$app->redirect()$app->pass()等引发的异常的try/catch块中触发事件。这意味着我们可以在这里实现我们的检查/重定向逻辑,就好像这是一个路由处理函数。

Above is_route_protected and user_has_permission are just pseudo-code to illustrate how my auth middleware worked. 上面是is_route_protecteduser_has_permission只是伪代码,用于说明我的身份验证中间件的工作原理。 I structured the class so that you could specify a list of routes or regex for routes in the Middleware constructor that were protected, as well as passing a service object that implemented the user permission checking, etc. Hope this helps. 我构建了类,以便您可以为中间件构造函数中受保护的路由指定路由或正则表达式列表,以及传递实现用户权限检查的服务对象,等等。希望这会有所帮助。

There is an alternative method of doing this, as I've been in the same situation. 有一种替代方法可以做到这一点,因为我一直处于相同的情况。 What I wanted to avoid was matching anything by route and wanted to use route names instead, so you could try the following: 我想避免的是通过路由匹配任何东西并且想要使用路由名称,所以你可以尝试以下方法:

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();
}

You could even have an array of routes you DON'T want the middleware to run on and then just check if it's in_array() etc and if not, do what you need to. 您甚至可以拥有一系列您不希望运行中间件的路由,然后只检查它是否为in_array()等,如果没有,请执行您需要的操作。

You should use app->request()->getPathInfo() instead of app->getRoute(). 您应该使用app-> request() - > getPathInfo()而不是app-> getRoute()。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM