Slim PHP Route in Middleware

2020-02-21 08:18发布

In Slim is it possible to get the current route within middleware?

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. Any help would be greatly appreciated.

3条回答
淡お忘
2楼-- · 2020-02-21 08:30

You should use app->request()->getPathInfo() instead of app->getRoute().

class Auth extends \Slim\Middleware{
    public function call(){ 
        $currentRoute = $this->app->request()->getPathInfo();
    }
}
查看更多
贼婆χ
3楼-- · 2020-02-21 08:49

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.

查看更多
够拽才男人
4楼-- · 2020-02-21 08:54

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. It is in this method that Slim parses and processes the route. In which case, you cannot access $app->router()->getCurrentRoute() in the Middleware::call method because it won't have been parsed and defined yet.

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.

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. 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.

Above is_route_protected and user_has_permission are just pseudo-code to illustrate how my auth middleware worked. 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.

查看更多
登录 后发表回答