Skip to content

Commit 3733dab

Browse files
authored
Merge pull request #7419 from kenjis/fix-spark-routes-auto-routing
fix: [Auto Routing Improved] spark routes shows invalid routes
2 parents e0e9531 + 93de9ac commit 3733dab

4 files changed

Lines changed: 110 additions & 8 deletions

File tree

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ public function read(string $class, string $defaultController = 'Home', string $
6565
// Remove HTTP verb prefix.
6666
$methodInUri = lcfirst(substr($methodName, strlen($httpVerb)));
6767

68+
// Check if it is the default method.
6869
if ($methodInUri === $defaultMethod) {
69-
$routeWithoutController = $this->getRouteWithoutController(
70+
$routeForDefaultController = $this->getRouteForDefaultController(
7071
$classShortname,
7172
$defaultController,
7273
$classInUri,
@@ -75,8 +76,11 @@ public function read(string $class, string $defaultController = 'Home', string $
7576
$httpVerb
7677
);
7778

78-
if ($routeWithoutController !== []) {
79-
$output = [...$output, ...$routeWithoutController];
79+
if ($routeForDefaultController !== []) {
80+
// The controller is the default controller. It only
81+
// has a route for the default method. Other methods
82+
// will not be routed even if they exist.
83+
$output = [...$output, ...$routeForDefaultController];
8084

8185
continue;
8286
}
@@ -113,6 +117,12 @@ public function read(string $class, string $defaultController = 'Home', string $
113117
$params[$param->getName()] = $required;
114118
}
115119

120+
// If it is the default controller, the method will not be
121+
// routed.
122+
if ($classShortname === $defaultController) {
123+
$route = 'x ' . $route;
124+
}
125+
116126
$output[] = [
117127
'method' => $httpVerb,
118128
'route' => $route,
@@ -151,9 +161,11 @@ private function getUriByClass(string $classname): string
151161
}
152162

153163
/**
154-
* Gets a route without default controller.
164+
* Gets a route for the default controller.
165+
*
166+
* @phpstan-return list<array>
155167
*/
156-
private function getRouteWithoutController(
168+
private function getRouteForDefaultController(
157169
string $classShortname,
158170
string $defaultController,
159171
string $uriByClass,

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

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved;
1313

14+
use CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved\Controllers\Home;
1415
use CodeIgniter\Test\CIUnitTestCase;
1516
use Tests\Support\Controllers\Newautorouting;
1617
use Tests\Support\Controllers\Remap;
@@ -22,13 +23,13 @@
2223
*/
2324
final class ControllerMethodReaderTest extends CIUnitTestCase
2425
{
25-
private function createControllerMethodReader(): ControllerMethodReader
26-
{
26+
private function createControllerMethodReader(
27+
string $namespace = 'Tests\Support\Controllers'
28+
): ControllerMethodReader {
2729
$methods = [
2830
'get',
2931
'post',
3032
];
31-
$namespace = 'Tests\Support\Controllers';
3233

3334
return new ControllerMethodReader($namespace, $methods);
3435
}
@@ -63,6 +64,41 @@ public function testRead()
6364
$this->assertSame($expected, $routes);
6465
}
6566

67+
public function testReadDefaultController()
68+
{
69+
$reader = $this->createControllerMethodReader(
70+
'CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved\Controllers'
71+
);
72+
73+
$routes = $reader->read(Home::class);
74+
75+
$expected = [
76+
0 => [
77+
'method' => 'get',
78+
'route' => '/',
79+
'route_params' => '',
80+
'handler' => '\CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved\Controllers\Home::getIndex',
81+
'params' => [],
82+
],
83+
[
84+
'method' => 'post',
85+
'route' => '/',
86+
'route_params' => '',
87+
'handler' => '\CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved\Controllers\Home::postIndex',
88+
'params' => [],
89+
],
90+
[
91+
'method' => 'get',
92+
'route' => 'x home/foo',
93+
'route_params' => '',
94+
'handler' => '\CodeIgniter\Commands\Utilities\Routes\AutoRouterImproved\Controllers\Home::getFoo',
95+
'params' => [],
96+
],
97+
];
98+
99+
$this->assertSame($expected, $routes);
100+
}
101+
66102
public function testReadControllerWithRemap()
67103
{
68104
$reader = $this->createControllerMethodReader();
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CodeIgniter 4 framework.
5+
*
6+
* (c) CodeIgniter Foundation <admin@codeigniter.com>
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\Commands\Utilities\Routes\AutoRouterImproved\Controllers;
13+
14+
use CodeIgniter\Controller;
15+
16+
/**
17+
* The default controller for Auto Routing (Improved)
18+
*/
19+
class Home extends Controller
20+
{
21+
public function getIndex()
22+
{
23+
}
24+
25+
public function postIndex()
26+
{
27+
}
28+
29+
/**
30+
* This method cannot be accessible.
31+
*/
32+
public function getFoo()
33+
{
34+
}
35+
}

user_guide_src/source/incoming/routing.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,25 @@ The *Method* will be like ``GET(auto)``.
829829

830830
``/..`` in the *Route* column indicates one segment. ``[/..]`` indicates it is optional.
831831

832+
If you see a route starting with ``x`` like the following, it indicates an invalid
833+
route that won't be routed, but the controller has a public method for routing.
834+
835+
.. code-block:: none
836+
837+
+-----------+----------------+------+-------------------------------------+----------------+---------------+
838+
| Method | Route | Name | Handler | Before Filters | After Filters |
839+
+-----------+----------------+------+-------------------------------------+----------------+---------------+
840+
| GET(auto) | x home/foo | | \App\Controllers\Home::getFoo | <unknown> | <unknown> |
841+
+-----------+----------------+------+-------------------------------------+----------------+---------------+
842+
843+
The above example shows you have the ``\App\Controllers\Home::getFoo()`` method,
844+
but it is not routed because it is the default controller (``Home`` by default)
845+
and the default controller name must be omitted in the URI. You should delete
846+
the ``getFoo()`` method.
847+
848+
.. note:: Prior to v4.3.4, the invalid route is displayed as a normal route
849+
due to a bug.
850+
832851
Auto Routing (Legacy)
833852
---------------------
834853

0 commit comments

Comments
 (0)