Slim 3 multiple routes to one function?
Asked Answered
C

4

8

I've been looking all over online and can't find anything that tells you how to assign multiple routes to one callback. For example I want to move:

$app->get('/sign-in', function($request, $response) {
    return $this->view->render($response, 'home.twig');
});

$app->get('/login', function($request, $response) {
    return $this->view->render($response, 'home.twig');
});

into something like:

$app->get(['/sign-in', '/login'], function($request, $response) {
    return $this->view->render($response, 'home.twig');
});

Is there a way to do this with Slim 3? I found online that in Slim 2 you could use the conditions([]); function on the end to chain multiple routes to one callback.

Clos answered 28/3, 2017 at 1:0 Comment(7)
Since you're already using an MVC-like structure, have you considered using a controller instead of putting closures in the routes file directly?Cowrie
@Cowrie I'm quite new to this whole type of structure, would you mind explaining in a bit more detail what you mean? Maybe provide a code example? Thanks!Clos
Controllers are a bit hard to explain in a comment, but I'll give it a go in an answer.Cowrie
@Cowrie Thanks, I really appreciate it!Clos
Actually, reviewing your comments on the other answer, I'm not sure that's the way to go about things. I would recommend using controllers anyway, to keep your logic separate and to help keep you organized, but it may not be relevant. I'm not sure there's a way of doing it with just an array of route paths---seems you'd have to do it with repeated ->get() calls.Cowrie
The way that Steve described could work, it's not the cleanest but definitely makes it a lot easier to modify all the code at once.Clos
I'm afraid that's the cleanest it would get. Though, again, look into controllers if you want to keep your logic clean and separate. Codecourse has a tutorial on Slim 3 controllers, but it seems you have to have an account to view the full series and I forget if CC is paywalled.Cowrie
C
4

It seems that you can simply define an array and loop through it to create multiple routes on one funciton.

$routes = [
    '/',
    '/home', 
    '/sign-in',
    '/login',
    '/register',
    '/sign-up',
    '/contact'
];

foreach ($routes as $route) {
    $app->get($route, function($request, $response) {
        return $this->view->render($response, 'home.twig');
    });
}
Clos answered 28/3, 2017 at 1:36 Comment(2)
This would certainly work, so +1. Though i personally find it less intuitive than explicit routes with a shared function / method.Ventricular
@Ventricular yeah. I see the benefits to both methods. I prefer the one I found because with my application I can simply add a new route to the array and it's done instead of having to create another get.Clos
V
3

Just create the function as a closure and pass it as a parameter:

$home = function($request, $response) {
    return $this->view->render($response, 'home.twig');
};

$app->get('/sign-in', $home);

$app->get('/login',   $home);

Or use a named function:

function home($request, $response) {
    return $this->view->render($response, 'home.twig');
};
$app->get('/sign-in', 'home');

$app->get('/login',   'home');
Ventricular answered 28/3, 2017 at 1:18 Comment(4)
This could very easily work but I would prefer a way where I could just pass an array of routes to $app->get(). Is this even possible?Clos
Not a frequant Slim user, so i can only point your here: #11521764 but personally i prefer to have explicit routes, even if they share a callback ( or indeed controller method as suggested by @Cowrie )Ventricular
FYI @Steve, that question/answer is for Slim 2, and unfortunately no longer relevant.Cowrie
@Cowrie yes, thats always an issue when replying without current framework knowledge. Hopefully someone else can contribute an alternative, though i stand by my preference for explicit routes, regardless of framework or programming languageVentricular
J
1

FastRoute doesn't do what you want, however, you can use a parameter that is limited via regex to the list of urls that you want to use:

$app->get("/{_:sign-in|login}", function ($request, $response) {
    $response->write("Hello!");
    return $response;
});

Note that you have to have an argument name, so I've use _ as it's inoffensive.

Josey answered 29/3, 2017 at 6:48 Comment(0)
R
0

I am using regex to do this trick:

$app->get('/{router:login|sign-in}', function ($request, $response, $args) {
  echo "Hello, " . $args['router'];
});
Revest answered 7/12, 2017 at 18:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.