Skip to content

Commit 4397d42

Browse files
authored
Merge pull request #7162 from kenjis/feat-auto-routes-index-fallback
feat: [Auto Routing Improved] fallback to default method
2 parents a9d816e + 6400946 commit 4397d42

File tree

12 files changed

+134
-19
lines changed

12 files changed

+134
-19
lines changed

system/Commands/Utilities/Routes/AutoRouterImproved/ControllerMethodReader.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,37 @@ public function read(string $class, string $defaultController = 'Home', string $
7676
);
7777

7878
if ($routeWithoutController !== []) {
79+
// Route for the default controller.
7980
$output = [...$output, ...$routeWithoutController];
8081

8182
continue;
8283
}
8384

85+
$params = [];
86+
$routeParams = '';
87+
$refParams = $method->getParameters();
88+
89+
foreach ($refParams as $param) {
90+
$required = true;
91+
if ($param->isOptional()) {
92+
$required = false;
93+
94+
$routeParams .= '[/..]';
95+
} else {
96+
$routeParams .= '/..';
97+
}
98+
99+
// [variable_name => required?]
100+
$params[$param->getName()] = $required;
101+
}
102+
84103
// Route for the default method.
85104
$output[] = [
86105
'method' => $httpVerb,
87106
'route' => $classInUri,
88-
'route_params' => '',
107+
'route_params' => $routeParams,
89108
'handler' => '\\' . $classname . '::' . $methodName,
90-
'params' => [],
109+
'params' => $params,
91110
];
92111

93112
continue;

system/Router/AutoRouterImproved.php

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace CodeIgniter\Router;
1313

1414
use CodeIgniter\Exceptions\PageNotFoundException;
15+
use CodeIgniter\Router\Exceptions\MethodNotFoundException;
1516
use ReflectionClass;
1617
use ReflectionException;
1718

@@ -168,17 +169,30 @@ public function getRoute(string $uri): array
168169
'\\'
169170
);
170171

171-
// Ensure routes registered via $routes->cli() are not accessible via web.
172+
// Ensure the controller is not defined in routes.
172173
$this->protectDefinedRoutes();
173174

174-
// Check _remap()
175+
// Ensure the controller does not have _remap() method.
175176
$this->checkRemap();
176177

177-
// Check parameters
178+
// Check parameter count
178179
try {
179180
$this->checkParameters($uri);
180-
} catch (ReflectionException $e) {
181-
throw PageNotFoundException::forControllerNotFound($this->controller, $this->method);
181+
} catch (MethodNotFoundException $e) {
182+
// Fallback to the default method
183+
if (! isset($methodSegment)) {
184+
throw PageNotFoundException::forControllerNotFound($this->controller, $this->method);
185+
}
186+
187+
array_unshift($this->params, $methodSegment);
188+
$method = $this->method;
189+
$this->method = $this->defaultMethod;
190+
191+
try {
192+
$this->checkParameters($uri);
193+
} catch (MethodNotFoundException $e) {
194+
throw PageNotFoundException::forControllerNotFound($this->controller, $method);
195+
}
182196
}
183197

184198
return [$this->directory, $this->controller, $this->method, $this->params];
@@ -201,12 +215,21 @@ private function protectDefinedRoutes(): void
201215

202216
private function checkParameters(string $uri): void
203217
{
204-
$refClass = new ReflectionClass($this->controller);
205-
$refMethod = $refClass->getMethod($this->method);
206-
$refParams = $refMethod->getParameters();
218+
try {
219+
$refClass = new ReflectionClass($this->controller);
220+
} catch (ReflectionException $e) {
221+
throw PageNotFoundException::forControllerNotFound($this->controller, $this->method);
222+
}
223+
224+
try {
225+
$refMethod = $refClass->getMethod($this->method);
226+
$refParams = $refMethod->getParameters();
227+
} catch (ReflectionException $e) {
228+
throw new MethodNotFoundException();
229+
}
207230

208231
if (! $refMethod->isPublic()) {
209-
throw PageNotFoundException::forMethodNotFound($this->method);
232+
throw new MethodNotFoundException();
210233
}
211234

212235
if (count($refParams) < count($this->params)) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace CodeIgniter\Router\Exceptions;
13+
14+
use RuntimeException;
15+
16+
/**
17+
* @internal
18+
*/
19+
final class MethodNotFoundException extends RuntimeException
20+
{
21+
}

tests/_support/Controllers/Newautorouting.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
class Newautorouting extends Controller
1717
{
18-
public function getIndex()
18+
public function getIndex(string $m = '')
1919
{
2020
return 'Hello';
2121
}

tests/system/Commands/RoutesTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public function testRoutesCommandAutoRouteImproved()
129129
| TRACE | testing | testing-index | \App\Controllers\TestController::index | | toolbar |
130130
| CONNECT | testing | testing-index | \App\Controllers\TestController::index | | toolbar |
131131
| CLI | testing | testing-index | \App\Controllers\TestController::index | | |
132-
| GET(auto) | newautorouting | | \Tests\Support\Controllers\Newautorouting::getIndex | | toolbar |
132+
| GET(auto) | newautorouting[/..] | | \Tests\Support\Controllers\Newautorouting::getIndex | | toolbar |
133133
| POST(auto) | newautorouting/save/../..[/..] | | \Tests\Support\Controllers\Newautorouting::postSave | | toolbar |
134134
+------------+--------------------------------+---------------+-----------------------------------------------------+----------------+---------------+
135135
EOL;

tests/system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollectorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function testGetFilterMatches()
6262
$expected = [
6363
0 => [
6464
'GET(auto)',
65-
'newautorouting',
65+
'newautorouting[/..]',
6666
'',
6767
'\\Tests\\Support\\Controllers\\Newautorouting::getIndex',
6868
'',
@@ -90,7 +90,7 @@ public function testGetFilterDoesNotMatch()
9090
$expected = [
9191
0 => [
9292
'GET(auto)',
93-
'newautorouting',
93+
'newautorouting[/..]',
9494
'',
9595
'\\Tests\\Support\\Controllers\\Newautorouting::getIndex',
9696
'',

tests/system/Commands/Utilities/Routes/AutoRouterImproved/ControllerMethodReaderTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ public function testRead()
4343
0 => [
4444
'method' => 'get',
4545
'route' => 'newautorouting',
46-
'route_params' => '',
46+
'route_params' => '[/..]',
4747
'handler' => '\Tests\Support\Controllers\Newautorouting::getIndex',
48-
'params' => [],
48+
'params' => [
49+
'm' => false,
50+
],
4951
],
5052
[
5153
'method' => 'post',

tests/system/Router/AutoRouterImprovedTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,19 @@ public function testAutoRouteFindsDefaultDashFolder()
199199
$this->assertSame([], $params);
200200
}
201201

202+
public function testAutoRouteFallbackToDefaultMethod()
203+
{
204+
$router = $this->createNewAutoRouter();
205+
206+
[$directory, $controller, $method, $params]
207+
= $router->getRoute('index/15');
208+
209+
$this->assertNull($directory);
210+
$this->assertSame('\\' . Index::class, $controller);
211+
$this->assertSame('getIndex', $method);
212+
$this->assertSame(['15'], $params);
213+
}
214+
202215
public function testAutoRouteRejectsSingleDot()
203216
{
204217
$this->expectException(PageNotFoundException::class);

tests/system/Router/Controllers/Index.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
class Index extends Controller
1717
{
18-
public function getIndex()
18+
public function getIndex($p1 = '')
1919
{
2020
}
2121

user_guide_src/source/changelogs/v4.4.0.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,11 @@ Helpers and Functions
5858

5959
Others
6060
======
61-
- **View:** Added optional 2nd parameter ``$saveData`` on ``renderSection()`` to prevent from auto cleans the data after displaying. See :ref:`View Layouts <creating-a-layout>` for details.
6261

62+
- **View:** Added optional 2nd parameter ``$saveData`` on ``renderSection()`` to prevent from auto cleans the data after displaying. See :ref:`View Layouts <creating-a-layout>` for details.
63+
- **Auto Routing (Improved)**: Now you can use URI without a method name like
64+
``product/15`` where ``15`` is an arbitrary number.
65+
See :ref:`controller-default-method-fallback` for details.
6366

6467
Message Changes
6568
***************

0 commit comments

Comments
 (0)