11

I want to get the name of the current I route in a middleware class. Previously (in Slim 2.*) you could fetch the current route like so:

$route = $this->app->router->getCurrentRoute();

But this function has been removed in the 3.0 version of Slim. I've found the following code in the __invoke method of Slim\App:

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

This indicates that the current route is stored as the attribute routeInfo in the Request. But it seems that my custom middleware class is called before the attribute is set (by the $this->dispatchRouterAndPrepareRoute($request, $router); method). Because calling $request->getAttribute('routeInfo') resolves to NULL.

So my question is; how can I get the current route (or the name of the route) from a middleware function/class?

Or should I just copy the piece of code above from Slim\App?

alexw
  • 7,044
  • 6
  • 46
  • 81
Wessel van der Linden
  • 2,214
  • 2
  • 17
  • 38
  • I am also having trouble getting the current route in middleware. I have set the `'determineRouteBeforeAppMiddleware' => true` and when I do `$route = $request->getAttribute('route');` I get an object(Slim\Route), but when I do `$routeName = $route->getName();` I get null. Anyone have any suggestion? – Paulo Borralho Martins Dec 15 '16 at 22:37
  • 1
    Did you name the route via the `setName()` method? (https://www.slimframework.com/docs/objects/router.html#route-names) – Wessel van der Linden Dec 15 '16 at 23:18
  • Thx @Wessel. The problem was the missing `setName()` method after declaring the route. – Paulo Borralho Martins Dec 16 '16 at 07:51

5 Answers5

10

For Slim3, here is an example showing you how to get routing information from within middleware, which is actually a combination of previous answers put together.

<?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....
})

In my case, I wanted to add middleware that would ensure the user was logged in on certain routes, and redirect them to the login page if they weren't. I found the easiest way to do this was to use ->setName() on the routes like so:

$app->get('/', function (\Slim\Http\Request $request, Slim\Http\Response $response, $args) {
    return $response->withRedirect('/home');
})->setName('index');

Then if this route was matched, the $routeName in the middleware example will be "index". I then defined my array list of routes that didn't require authentication and checked if the current route was in that list. E.g.

if (!in_array($routeName, $publicRoutesArray))
{
    # @TODO - check user logged in and redirect if not.
}
Programster
  • 11,048
  • 8
  • 43
  • 51
9
$request->getUri()->getPath()

Get current Route, even in middleware.

Bhargav Rao
  • 41,091
  • 27
  • 112
  • 129
Anuga
  • 1,880
  • 13
  • 22
7

Apparently you can configure Slim to determine the route before going into the middleware with this setting:

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

I'm not sure what kind of impact this has, but it works for me :)

Wessel van der Linden
  • 2,214
  • 2
  • 17
  • 38
  • 2
    Once you do this, using @SamarRizvi answer works with using `$routeInfo = $request->getAttribute('routeInfo');` inside the middleware. Without this, $routeInfo is nothing. – Programster Aug 24 '16 at 09:38
  • This is specifically for App middleware. Also, if the route *doesn't* exist then `$route` will be null in @SamarRizvi's answer with this setting change. – scottheckel Apr 10 '18 at 21:00
1

Does the following provide you with sufficient information you require or do you also need the 'request' bit in routeInfo?

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

If you also require the 'request' bit then you will need to manually do the same thing dispatchRouterAndPrepareRoute does.

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

Hope this helps.

binarix
  • 11
  • 2
0

Here's how you get current route in your middleware in Slim framework 3:

$routeInfo = $request->getAttribute('routeInfo');

Note that you should use this inside __invoke() function in your middleware. Here's the sample usage:

public function __invoke($request, $response, $next)
    {
        ....
        $routeInfo = $request->getAttribute('routeInfo');
        ....
    }

$routeInfo shall then contain an object like:

{
    "0": 1,
    "1": "route6",
    "2": {
      "name": "loremipsum"
    },
    "request": [
      "POST",
      "http://example.org/loremipsum"
    ]
  }
Samar Rizvi
  • 190
  • 9