Jawad Le Wywadi Jawad Le Wywadi - 2 months ago 59
PHP Question

Optional parameters in url - Slim 3

I have a pretty straightforward question. I am using Slim 3 to build a RESTfull api.

How come this works:

$app->get('/news[/{params:.*}]', function ($request, $response, $args) {
$params = explode('/', $request->getAttribute('params'));
$response->write("news!");
return $response;

});


But not this:

$app->get('/news[/{params:.*}]/details', function ($request, $response, $args) {
$params = explode('/', $request->getAttribute('params'));
$response->write("news details");
return $response;

});


In fact the latter does not compile.

Answer

Using unlimited Optional segments, implies that each consequent segment is reserved.

In your defined route for /news[/{params:.*}] the following paths qualify:

/news
/news/foo
/news/foo/bar
/news/foo/bar/... 

So adding an extra fixed segment /details won't work if you add it after the square brackets.

When you define it as /news[/{params:.*}/details] with the /details segment within the square brackets it does work for details, but not in combination with the first route & will break. You can still go with your first route & check the last param, or with an optional param within:

$app->get('/news[/{params:.*}[/details]]', function ($request, $response, $args) {

    $params = explode('/', $request->getAttribute('params'));

    if (end($params) != 'details') {

        $response->write("news!");

    } else {

        // $params for details;
        array_pop($params);

        $response->write("news details");
    }

    // $params is an array of all the optional segments
    var_dump($params);

});

Update:

The actual problem here seems like a colliding definition in the routes, where for example the unlimited optional segments would always match the second defined route. It can be solved by defining the routes with a route regex & enclosing them in a route group prior to non-colliding matches:

$app->group('/news', function () {

    $this->map(['GET'], '', function ($request, $response, $args) {

        $response->write("news w/o params");

    })->setName('news');

    // Unlimited optional parameters not ending with "/details"
    $this->get('/{params:[[:alnum:]\/]*[^\/details]}', function ($request, $response, $args) {
        $params = explode('/', $request->getAttribute('params'));

        var_dump($params);

        $response->write("news!");
    });

    // Unlimited optional parameters ending with "/details"
    $this->get('/{params:[[:alnum:]\/]*\/details}', function ($request, $response, $args) {
        $params = explode('/', $request->getAttribute('params'));
        array_pop($params); // fix $params

        var_dump($params);

        $response->write("news details");
    });

});