Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access all routes from Slim 3 php framework?

Tags:

php

slim

psr-7

I am trying to build a dynamic drop-down menu from routes defined in Slim framework and here is my question - is there a way to access all defined static routes from some kind of array?

For instance, if I define my routes like this:

// Index page: '/'
require_once('pages/main.php');

// Example page: '/hello'
require_once('pages/hello.php');

// Example page: '/hello/world'
require_once('pages/hello/world.php');

// Contact page: '/contact'
require_once('pages/contact.php');

Each file is a separate page that looks like this

// Index page
$app->get('/', function ($request, $response, $args) {

    // Some code

})->setName('index');

I would like to access all of these defined routes from some sort of array and then use that array to make a unordered HTML list in my template files.

<ul>
  <li><a href="/">Index</a></li>
  <li><a href="/hello">Hello</a>
    <ul>
       <li><a href="/hello/world">World</a></li>
    </ul>
  </li>
  <li><a href="/contact">Contact</a></li>
</ul>

Whenever I change defined routes, I would like this menu to change with it. Is there a way to achieve this?

like image 806
Vladimir Jovanović Avatar asked Nov 09 '16 11:11

Vladimir Jovanović


3 Answers

A quick search of the Router class in GitHub project for Slim shows a public method getRoutes(), which returns the $this->routes[] array of route objects. From the route object you can get the route pattern using the getPattern() method:

$routes = $app->getContainer()->router->getRoutes();
// And then iterate over $routes

foreach ($routes as $route) {
    echo $route->getPattern(), "<br>";
}

Edit: Added example

like image 109
Wolf Avatar answered Nov 10 '22 10:11

Wolf


Yes. You can name your routes in Slim. This is done in a very simple manner:

$app->get('/hello', function($request, $response) {
    // Processing request...
})->setName('helloPage'); // setting unique name for route

Now you can get URL by name like this:

$url = $app->getContainer()->get('router')->pathFor('helloPage');
echo $url; // Outputs '/hello'

You can name routes with placeholders too:

// Let's define route with placeholder
$app->get('/user-profile/{userId:[0-9]+}', function($request, $response) {
    // Processing request...
})->setName('userProfilePage');

// Now get the url. Note that we're passing an array with placeholder and its value to `pathFor`
$url = $app->getContainer()->get('router')->pathFor('helloPage', ['userId': 123]);
echo $url; // Outputs '/user-profile/123'

This is sure the way to go, because if you reference routes by names in your templates, then if you need to change a URL, you need to do it only in route defenition. I find this particuarly cool.

like image 4
Georgy Ivanov Avatar answered Nov 10 '22 11:11

Georgy Ivanov


as i've commented in the corresponding issue of slim:

$routes = array_reduce($this->app->getContainer()->get('router')->getRoutes(), function ($target, $route) {
    $target[$route->getPattern()] = [
        'methods' => json_encode($route->getMethods()),
        'callable' => $route->getCallable(),
        'middlewares' => json_encode($route->getMiddleware()),
        'pattern' => $route->getPattern(),
    ];
    return $target;
}, []);
die(print_r($routes, true));
like image 2
scones Avatar answered Nov 10 '22 12:11

scones