How to do something with request in group

I’m trying to do something with a request in a group, because all methods in that group reuse a certain object.
I’ve tried two different approaches, but can’t get it to work.

Am I approaching this all wrong? This is my first time using anything like Slim, sorry if it’s a stupid question.

First try:

$app->group('/orders/{id}', function () {
    $id = $request->getAttribute('id'); //can't access $request here
    $order = getOrderFromDB($id);

    $this->get('',         function ($order) {...});
    $this->post('/delete', function ($order) {...});
    $this->post('/update', function ($order) {...});
});

Second try with middleware:

$app->group('/orders/{id}', function () {
    $this->get('',         function ($request) {...});
    $this->post('/delete', function ($request) {...});
    $this->post('/update', function ($request) {...});
})->add(function ($request, $response, $next) {
    $id = $request->getAttribute('id'); //doesn't work?
    $order = getOrderFromDB($id);
    $request = $request->withAttribute('order', $order);
    return $next($request, $response);
});

Have you looked at https://www.slimframework.com/docs/objects/router.html#route-groups?

Yes, I think I understand the concept of groups, but what I’m trying to do is do some logic for all routes in the group (e.g. fetch something from a database), and then do something specific with it per route (e.g. display, update or delete it).
I can’t find something like that in the docs. Is it possible?

@lonaowna My usual setup is as follows:

$c = $app->getContainer();

// instantiate the route controller and use the order model as a dependency
$c['OrderController'] = function() {
	$order = new Order;
	return new OrderController($order);
};

// call a controller method based on the route
$app->group('/orders/{id}', function () {
    $this->get('','OrderController:getOrder');
    $this->post('/delete', 'OrderController:deleteOrder');
    $this->post('/update','OrderController:updateOrder');
});

// controller class
class OrderController {

	public function __construct($order) {
		$this->order = $order;
	}

    // get the id from the url via $params 
	public function getOrder($request,$response,$params) {
		$order = $this->order->getOrderFromDB($params['id']);
		return $response->withJson($order);
	}
} 

Instantiating the class with the ID is something I’ve thought about also, but really haven’t found an elegant way to go about it. You could use middleware to do this but for me it doesn’t seem right. I’m curious if anyone else has any suggestions on how to accomplish this. As far as I know, you can’t get the url parameters in a container.

@robrothedev that looks like a good solution, thanks! :smile:

Any thoughts about the following approach? (basically just implementing “group” myself)

I really can’t see what the advantage of using a group is. The only thing is that it maybe better separates the concepts of routing and actual logic, but this seems so much more flexible.

$app->post('/orders/{id}/{action}', function ($request, $response) {
	$id = $request->getAttribute('id');
	$order = getOrderFromDB($id);
	switch ($request->getAttribute('action')) {
		case 'update':
			$order->update();
			break;

		case 'delete':
			$order->delete();
			break;
	}
});

@lonaowna There are a couple advantages for using groups. Here’s one example where a certain route and all requests on that route need to be made by a valid user:

$validateUser = function($request,$response,$next) {
	if (!$_SESSION['user']) {
		return $response->withHeader('Location','/login');
	}
	return $next($request,$response);
};

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

	$this->get('/users',''):
	$this->get('/users/{id}',''):
	$this->post('/users','');
	$this->put('/users/{id}','');

})->add($validateUser); 

So rather than adding the middleware on each of those requests, I can group my routes and have the middleware handle ANY request made to ‘/admin’.

Also, I prefer to specify the request being made rather than an action variable. So rather than a blanket post request where your code has to decide what to do with it, you can setup the post, put and delete requests. By doing so, you know EXACTLY what’s going on for that request.

@robrothedev right, I agree that in most cases using a group would be better. For this particular case I think I still try out the switch method though, just because all “actions” are very similar.

Thanks again for your insight!