I didn't work with DICE until now, though I looked in its implementation in order to present the first option to you. I hope it will work. If not, feel free to read the DICE documentation/code regarding the call
rule and the create
method.
Note: The title should be something like "FastRoute: Pass route parameters to handler", or "FastRoute: Pass route arguments to handler", because a prefix is defined as the route part which is prepended to each route pattern inside of a route group.
Option 1: Use the call
rule of the DI container (DICE):
This is, of course, the recommended way, since the DI container automatically injects the method arguments. Which could be more than the ones read from the route!
Note: controller method =: "action".
See (in DICE docs):
Route:
$router->addRoute('GET', '/{userName}[/{userId:\d+}]', ['UserController', 'list']);
Note: if you have optional route parts, then you have to define the corresponding action parameters as optional.
Dispatching request by FastRoute:
case FastRoute\Dispatcher::FOUND:
$controllerName = $routeInfo[1][0]; // "UserController"
$action = $routeInfo[1][1]; // "list" action
$parameters = $routeInfo[2]; // Action parameters list (e.g. route parameters list)
$rule['call'] = [ // Define the method to be called and the parameters to be passed to the further created controller.
[$action, $parameters],
];
$dice->addRule($controllerName, $rule);
$controller = $dice->create($controllerName); // UserController instance
break;
Action in UserController:
public function list($userName, $userId = NULL) {
return 'User name = ' . $userName . ', User id = ' . $userId ?? 'N/A';
}
Option 2: Call the action (without DICE), separately passing all route parameters to it:
Route:
The same.
Dispatching request by FastRoute:
case FastRoute\Dispatcher::FOUND:
$controllerName = $routeInfo[1][0]; // "UserController"
$action = $routeInfo[1][1]; // "list" action
$parameters = $routeInfo[2]; // Action parameters list (e.g. route parameters list)
$controller = $dice->create($controllerName); // UserController instance
call_user_func_array(
[$controller, $action] // callable
, $parameters
);
break;
Action in UserController:
public function list($userName, $userId = NULL) {
return 'User name = ' . $userName . ', User id = ' . $userId ?? 'N/A';
}
Option 3: Call the action (without DICE), passing an instance of a Request class:
Assign the route parameters list to a Request
instance (See PSR-7), as attribute, and pass the instance as action argument.
Route:
The same.
DI container definitions:
// Share a Request instance.
$dice->addRule('Request', ['shared' => true]);
Dispatching request by FastRoute:
case FastRoute\Dispatcher::FOUND:
$controllerName = $routeInfo[1][0]; // "UserController"
$action = $routeInfo[1][1]; // "list" action
$parameters = $routeInfo[2]; // Action parameters list (e.g. route parameters list)
// Create Request instance.
$request = $dice->create('Request');
// Assign the route parameters list to the Request instance.
$request->setAttribute('parameters') = $parameters
$controller = $dice->create($controllerName); // UserController instance
call_user_func_array(
[$controller, $action] // callable
, [$request]
);
break;
Action in UserController:
public function list(ServerRequestInterface $request) {
$userName = $request->getAttribute('parameters')['userName'];
$userId = $request->getAttribute('parameters')['userId'] ?? 'N/A';
return 'User name = ' . $userName . ', User id = ' . $userId ?? 'N/A';
}