0

How can I do 'or' in the route?

for instance, /about and /fr/about are pointing to the same objects/classes/methods. So instead of:

$app->get('/{url:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});

$app->get('/{language:[fr|en]+}/{url:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});

I tried with this:

$app->get('/{url:[a-zA-Z0-9\-]+}|/{language:[fr|en]+}/{url:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});

I get this error:

Type: FastRoute\BadRouteException
Message: Cannot use the same placeholder "url" twice
File: /var/www/mysite/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php

Any ideas what how to resolve this issue?

Or any solutions to avoid repeating the code?

Run
  • 54,938
  • 169
  • 450
  • 748
  • the error comes from your last route pattern, you reference url twice... you need to not use the same token twice. – geggleto Sep 14 '16 at 17:57
  • @geggleto any solutions to avoid repeating the code then? – Run Sep 14 '16 at 18:00
  • To not duplicate code may look into http://www.slimframework.com/docs/objects/router.html#container-resolution – danopz Sep 14 '16 at 22:15

2 Answers2

2

Here's why what you are trying does not work.

Your Routing:

$app->get('/{url:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});

$app->get('/{language:[fr|en]+}/{url:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});

FastRoute finds the first match and dispatches. If you look at this, your first route matches both /about and /fr/about So it gets dispatched first... In fact, it will always dispatch first, always.

What you actually want is to reorder the route definitions.

$app->get('/{language:[fr|en]+}/{url:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});
// ADD OTHER ROUTES HERE

// CATCH ALL
$app->get('/{url:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});

To solve the URL duplication problem... simply define a different token.

$app->get('/{url:[a-zA-Z0-9\-]+}|/{language:[fr|en]+}/{url2:[a-zA-Z0-9\-]+}', function (Request $request, Response $response, array $args) {
    // same staff
});
geggleto
  • 2,605
  • 1
  • 15
  • 18
1

If changing the order of the placeholders is possible for you, you could implement it in this manner:

$app->get('/{url:[a-zA-Z0-9\-]+}[/{language:[en|fr]+}]', function($request, $response, $args) {
    // code here...
});

By "changing the order of the placeholders" I mean the url comes first, then the language, so instead of fr/about you use about/fr.

The solution utilizes Slim's built-in optional segments: note the square brackets that wrap "language" placeholder.

It, however, requires that the optional segments are placed at the end of the route, otherwise you get FastRoute\BadRouteException.

Georgy Ivanov
  • 1,573
  • 1
  • 17
  • 24