Get a route pattern/regex?

Considering this route:
$app->map(['GET', 'POST'], '/step[/{step:[1-5]+}]', App\Controller\StepController::class)->setName('step');

How can my controller/middleware get access to used pattern?
Basicly I need this part to work with it further:

β€˜/step[/{step:[1-5]+}]’

$args['step'];

Does the Regular Expression Matching section in the Router docs help?

Or, in another example:

Perhaps I explained poorly.
What I need is literally β€˜/step[/{step:[1-5]+}]’.

$route contains the pattern but it is protected:
$route = $request->getAttribute('route');
[pattern:protected] => /step[/{step:[1-5]+}]

Is there a way to get that into my controller or middleware?

You can extend the Slim\Route class and provide a public getter for pattern. Since the route is created in Slim\Router class and there is no factory class you can pass in, you need to extend Slim\Router as well. For example:

<?php

require_once __DIR__ . '/vendor/autoload.php';

// extend Route to provide public getter for pattern
class MyRoute extends Slim\Route
{
    public function getPattern() {
        return $this->pattern;
    }
}

// extend router to use the extended Route class
class MyRouter extends Slim\Router
{
    protected function createRoute($methods, $pattern, $callable)
    {
        $route = new MyRoute($methods, $pattern, $callable, $this->routeGroups, $this->routeCounter);
        if (!empty($this->container)) {
            $route->setContainer($this->container);
        }

        return $route;
    }
}

// Set the router in the container, so Slim uses the extended Router class instance
$app = new Slim\App(['router' => new MyRouter()]);

$app->get('/step[/{step:[1-5]+}]', function (Slim\Http\Request $request, Slim\Http\Response $response, array $params) {
    $route = $request->getAttribute('route');

    return $route->getPattern();
});

$app->run();

Another way would be to pass in the pattern as an argument for the controller. You’d have to specify the pattern twice, but you won’t need to extend classes:

$app->get('/step[/{step:[1-5]+}]', function (Slim\Http\Request $request, Slim\Http\Response $response, array $params) {
    $controller = new SomeController('/step[/{step:[1-5]+}]'); // pass pattern by constructor

    return $controller->someAction($request, $response, $params);
});

A more hackish way, that I don’t particularly recommend, would be to use ReflectionProperty to gain access to the property:

    $property = new \ReflectionProperty(get_class($route), 'pattern');
    $property->setAccessible(true);
    return $property->getValue($route);

Also, you can create a pull request that adds a public getter for the pattern :wink: Once accepted, there is no needed for jumping through hoops to get this variable.

Hope that helps,

Lennaert

Thanks very much, that is great code that even works and returns the pattern.
I probally will ask for a getPattern public function, there are usercases where one needs just the pattern.

1 Like