When the router invokes a handler (closure or controller method), it builds the argument list automatically.
For each parameter, in order:
- Class-typed parameter (e.g.
RequestInterface $request):- If it matches the current request or response, the shared instance is injected.
- Otherwise, if a container is set, the value is fetched from it.
- Otherwise the class is instantiated, resolving its own constructor dependencies recursively.
- Built-in / untyped parameter: filled from the next captured route value, then a default value, then
nullif the parameter is nullable.
If a required built-in parameter cannot be filled, a
InitPHP\Router\Exception\RouterException is thrown.
$router->get('/users/{id}', function (Request $request, Response $response, $id) {
// $request, $response -> shared instances; $id -> captured value
return $response->withHeader('X-User', (string) $id);
});Type-hint a service and it will be constructed (and its dependencies resolved) for you:
class ReportService
{
public function __construct(private Clock $clock) {}
}
$router->get('/report', function (ReportService $reports) {
// $reports is built automatically, with a Clock injected into it
});Constructor parameters that cannot be resolved (e.g. a required scalar with no
value) cause a RouterException.
Pass a PSR-11 ContainerInterface and the
router will resolve controllers and class-typed dependencies through it:
use Psr\Container\ContainerInterface;
/** @var ContainerInterface $container */
$router = new Router($request, $response, ['container' => $container]);
$router->get('/', 'App\Controllers\HomeController@index');
// HomeController is fetched from the container.When a container is configured, the router asks it for the class first; if the container returns a non-object, the router falls back to instantiating the class itself.
By default, a parameter type-hinted with your concrete request/response class
receives the shared instance. Set argument_new_instance to true to
inject a freshly constructed instance instead:
$router = new Router($request, $response, ['argument_new_instance' => true]);This only affects request/response-typed parameters; the concrete class must be constructible for a new instance to be produced.
Next: Middleware.