Skip to content

Commit 26d6898

Browse files
committed
fix: support variadic FormRequest auto-routes and closure benchmark cleanup
1 parent 6bf52b1 commit 26d6898

4 files changed

Lines changed: 60 additions & 18 deletions

File tree

system/CodeIgniter.php

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,8 @@ protected function handleRequest(?RouteCollectionInterface $routes, ?Cache $cach
380380
if ($returned instanceof ResponseInterface) {
381381
$this->gatherOutput($returned);
382382
}
383-
// Closure controller has run in startController().
383+
// Closure controller has run in startController() - benchmarks were
384+
// stopped there as well.
384385
elseif (! is_callable($this->controller)) {
385386
$controller = $this->createController();
386387

@@ -392,9 +393,6 @@ protected function handleRequest(?RouteCollectionInterface $routes, ?Cache $cach
392393
Events::trigger('post_controller_constructor');
393394

394395
$returned = $this->runController($controller);
395-
} else {
396-
$this->benchmark->stop('controller_constructor');
397-
$this->benchmark->stop('controller');
398396
}
399397

400398
// If $returned is a string, then the controller output something,
@@ -589,9 +587,15 @@ protected function startController()
589587
// Is it routed to a Closure?
590588
if (is_object($this->controller) && ($this->controller::class === 'Closure')) {
591589
$controller = $this->controller;
592-
$resolved = $this->resolveCallableParams(new ReflectionFunction($controller), $this->router->params());
593590

594-
return $controller(...$resolved);
591+
try {
592+
$resolved = $this->resolveCallableParams(new ReflectionFunction($controller), $this->router->params());
593+
594+
return $controller(...$resolved);
595+
} finally {
596+
$this->benchmark->stop('controller_constructor');
597+
$this->benchmark->stop('controller');
598+
}
595599
}
596600

597601
// No controller specified - we don't know what to do now.
@@ -668,18 +672,20 @@ protected function runController($class)
668672

669673
// The controller method param types may not be string.
670674
// So cannot set `declare(strict_types=1)` in this file.
671-
if (method_exists($class, '_remap')) {
672-
// FormRequest injection is not supported for _remap() because its
673-
// signature is fixed to ($method, ...$params). Instantiate the
674-
// FormRequest manually inside _remap() if needed.
675-
$output = $class->_remap($this->method, ...$params);
676-
} else {
677-
$resolved = $this->resolveMethodParams($class, $this->method, $params);
678-
$output = $class->{$this->method}(...$resolved);
675+
try {
676+
if (method_exists($class, '_remap')) {
677+
// FormRequest injection is not supported for _remap() because its
678+
// signature is fixed to ($method, ...$params). Instantiate the
679+
// FormRequest manually inside _remap() if needed.
680+
$output = $class->_remap($this->method, ...$params);
681+
} else {
682+
$resolved = $this->resolveMethodParams($class, $this->method, $params);
683+
$output = $class->{$this->method}(...$resolved);
684+
}
685+
} finally {
686+
$this->benchmark->stop('controller');
679687
}
680688

681-
$this->benchmark->stop('controller');
682-
683689
return $output;
684690
}
685691

system/Router/AutoRouterImproved.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,12 +445,20 @@ private function checkParameters(): void
445445

446446
// FormRequest parameters are injected by the framework and do not
447447
// consume URI segments, so exclude them from the count.
448-
$uriParamCount = count(array_filter(
448+
$nonFormRequestParams = array_values(array_filter(
449449
$refParams,
450450
static fn ($p): bool => FormRequest::getFormRequestClass($p) === null,
451451
));
452452

453-
if ($uriParamCount < count($this->params)) {
453+
// A variadic parameter absorbs any number of trailing URI segments,
454+
// so there is no upper bound to enforce.
455+
foreach ($nonFormRequestParams as $p) {
456+
if ($p->isVariadic()) {
457+
return;
458+
}
459+
}
460+
461+
if (count($nonFormRequestParams) < count($this->params)) {
454462
throw new PageNotFoundException(
455463
'The param count in the URI are greater than the controller method params.'
456464
. ' Handler:' . $this->controller . '::' . $this->method

tests/system/Router/AutoRouterImprovedTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,30 @@ public function testUriParamCountExceedsNonFormRequestParams(): void
184184
$router->getRoute('mycontroller/formmethodwithparam/42/extra', Method::GET);
185185
}
186186

187+
public function testVariadicParamAlongsideFormRequestAcceptsMultipleUriSegments(): void
188+
{
189+
$router = $this->createNewAutoRouter();
190+
191+
[$directory, $controller, $method, $params]
192+
= $router->getRoute('mycontroller/formmethod-variadic/php/ci4/tags', Method::GET);
193+
194+
$this->assertSame('\\' . Mycontroller::class, $controller);
195+
$this->assertSame('getFormmethodVariadic', $method);
196+
$this->assertSame(['php', 'ci4', 'tags'], $params);
197+
}
198+
199+
public function testVariadicParamAlongsideFormRequestAcceptsZeroUriSegments(): void
200+
{
201+
$router = $this->createNewAutoRouter();
202+
203+
[$directory, $controller, $method, $params]
204+
= $router->getRoute('mycontroller/formmethod-variadic', Method::GET);
205+
206+
$this->assertSame('\\' . Mycontroller::class, $controller);
207+
$this->assertSame('getFormmethodVariadic', $method);
208+
$this->assertSame([], $params);
209+
}
210+
187211
public function testAutoRouteFindsControllerWithFile(): void
188212
{
189213
$router = $this->createNewAutoRouter();

tests/system/Router/Controllers/Mycontroller.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@ public function getFormmethod(MyFormRequest $request): void
3333
public function getFormmethodWithParam(string $id, MyFormRequest $request): void
3434
{
3535
}
36+
37+
public function getFormmethodVariadic(MyFormRequest $request, string ...$tags): void
38+
{
39+
}
3640
}

0 commit comments

Comments
 (0)