POST body, query params as $args


#1

Is there a way in v3 to pass POST body and/or query parameters to a route using the $args variable?

After finding no way around it I have made some custom middleware to set globals to be used in my route calls.

This feels janky and I would like to avoid it.


#2

They are not in $args, but you can get them from the request object.

public function __invoke(Request $request, Response $response, $args)
{
    $key = $request->getParsedBodyParam($key, $default = null);
    $parsedBody = $request->getParsedBody();
    $body = $request->getBody();
}

#3

Right. But can I put them into $args so that I have one place for arguments?

Thanks,

Tyler


#4

Not that I know of. IMHO they are not args so they don’t belong there.


#5

Ideally I would like to be able to pass them in the middleware like

$app->add(
  function($request, $response, $next) {
    $args = array();
    $args = array_merge($request->getParsedBody(), $request->getQueryParams());
    $response = $next($request, $response, $args);
    return $response;
});

But this would also need to not overwrite args that are set on individual routes. And having many routes means that I don’t want to have to do this on an individual level.


#6

Well, without getting into why you’d want to this (but feel free to enlighten me), Slim provides the withAttribute and getAttribute functions for passing data along to the route.

So, in your app middleware create a mash-up of the POST, QUERY and URL data, and pass it on in the request with withAttribute and then grab it in the route with getAttribute.

But it kinda smells.


#7

The feeling is that it is cleaner to have everything in one array, rather than separate calls for each piece or using globals.

Thanks,

Tyler


#8

But in what situation do you need to be testing for POST, GET or URL args? The args are either where you expect them to be, or they’re not. If you expected the query string to hold a variable, you wouldn’t go looking for it in POST. At the very least that would indicate your request has been messed with.


#9

A real life example that I can think of is one like this: A POST to v1/contacts/<ID>/records

So I have JSON in the POST body that I will have to get with $request->getParsedBody() or put it in a global in the middleware. And I will have $args given by the route definition.

If my route looks something like this:


$app->group(‘{contact_id:[0-9]+}’, function() as ($app) {

$app->get(‘’, MyClass::getMethod);

$app->post(‘/records’, MyClass::postMethod);

});

});


#10

I can’t imagine what kind of app would need to submit JSON data like that.

You only need one route, a POST route. That route processes the JSON.

Exactly what does interaction between the JSON data and the url segments consist of in your example? You’re either getting the records for a user with ID, or you’re submitting JSON to a POST route for that user. Either way you only need one route.


#11

Perhaps you misunderstood. I’m not submitting JSON in the URL or as URI, it’s in the request body, like normal.

Fair point not using a POST route with URI. It could be passed in the request body. But…I would still like that put into the $args variable so I don’t have to make a separate call to get the POST body.


#12

No, I understood exactly what you meant. But there’s absolutely no need to do it.

Feel free to ask about how to organise your routes. My sense of it is you’re trying to do too much with one request when it’s always better to break your app into discrete requests.


#13

We have about 20 routes so far. And I’ve followed REST API recomemdations. So I don’t feel the routes are disorganized. It’s more of wanting less code in each endpoint method. But I’ll take any advice into consideration.


#14

According to the Slim documentation the $args is for routing informations only.

Arguments
The third argument is an associative array that contains values for the current route’s named placeholders.

Therefore, it is simply not the right place to insert the parsed JSON data into $args. As @tflight already pointed out $parsedBody = $request->getParsedBody(); is the way to go.

The feeling is that it is cleaner to have everything in one array

This sounds like a evil global variable to me :wink:


#15

And that’s what we’ve done, via middleware.

Thanks,

Tyler