Skip to content

Commit 5eea88e

Browse files
committed
perf: change RouteCollection::$routes structure
1 parent 50ac4bb commit 5eea88e

File tree

1 file changed

+86
-41
lines changed

1 file changed

+86
-41
lines changed

system/Router/RouteCollection.php

Lines changed: 86 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,16 @@ class RouteCollection implements RouteCollectionInterface
110110
*
111111
* [
112112
* verb => [
113-
* routeName => [
114-
* 'route' => [
115-
* routeKey(regex) => handler,
116-
* or routeKey(regex)(from) => [routeKey(regex)(to) => handler], // redirect
117-
* ],
113+
* routeKey(regex) => [
114+
* 'name' => routeName
115+
* 'handler' => handler,
116+
* ],
117+
* // redirect route
118+
* or routeKey(regex)(from) => [
119+
* 'name' => routeName
120+
* 'handler' => [routeKey(regex)(to) => handler],
118121
* 'redirect' => statusCode,
119-
* ]
122+
* ],
120123
* ],
121124
* ]
122125
*/
@@ -133,6 +136,30 @@ class RouteCollection implements RouteCollectionInterface
133136
'cli' => [],
134137
];
135138

139+
/**
140+
* Array of routes names
141+
*
142+
* @var array
143+
*
144+
* [
145+
* verb => [
146+
* routeName => routeKey(regex)
147+
* ],
148+
* ]
149+
*/
150+
protected $routesNames = [
151+
'*' => [],
152+
'options' => [],
153+
'get' => [],
154+
'head' => [],
155+
'post' => [],
156+
'put' => [],
157+
'delete' => [],
158+
'trace' => [],
159+
'connect' => [],
160+
'cli' => [],
161+
];
162+
136163
/**
137164
* Array of routes options
138165
*
@@ -504,9 +531,8 @@ public function getRoutes(?string $verb = null): array
504531
// before any of the generic, "add" routes.
505532
$collection = $this->routes[$verb] + ($this->routes['*'] ?? []);
506533

507-
foreach ($collection as $r) {
508-
$key = key($r['route']);
509-
$routes[$key] = $r['route'][$key];
534+
foreach ($collection as $routeKey => $r) {
535+
$routes[$routeKey] = $r['handler'];
510536
}
511537
}
512538

@@ -603,11 +629,16 @@ public function add(string $from, $to, ?array $options = null): RouteCollectionI
603629
public function addRedirect(string $from, string $to, int $status = 302)
604630
{
605631
// Use the named route's pattern if this is a named route.
606-
if (array_key_exists($to, $this->routes['*'])) {
607-
$redirectTo = $this->routes['*'][$to]['route'];
608-
} elseif (array_key_exists($to, $this->routes['get'])) {
609-
$redirectTo = $this->routes['get'][$to]['route'];
632+
if (array_key_exists($to, $this->routesNames['*'])) {
633+
$routeName = $to;
634+
$routeKey = $this->routesNames['*'][$routeName];
635+
$redirectTo = [$routeKey => $this->routes['*'][$routeKey]['handler']];
636+
} elseif (array_key_exists($to, $this->routesNames['get'])) {
637+
$routeName = $to;
638+
$routeKey = $this->routesNames['get'][$routeName];
639+
$redirectTo = [$routeKey => $this->routes['get'][$routeKey]['handler']];
610640
} else {
641+
// The named route is not found.
611642
$redirectTo = $to;
612643
}
613644

@@ -623,11 +654,16 @@ public function addRedirect(string $from, string $to, int $status = 302)
623654
*/
624655
public function isRedirect(string $routeKey): bool
625656
{
626-
foreach ($this->routes['*'] as $name => $route) {
627-
// Named route?
628-
if ($name === $routeKey || key($route['route']) === $routeKey) {
629-
return isset($route['redirect']) && is_numeric($route['redirect']);
630-
}
657+
if (isset($this->routes['*'][$routeKey]['redirect'])) {
658+
return true;
659+
}
660+
661+
// This logic is not used. Should be deprecated?
662+
$routeName = $this->routes['*'][$routeKey]['name'] ?? null;
663+
if ($routeName === $routeKey) {
664+
$routeKey = $this->routesNames['*'][$routeName];
665+
666+
return isset($this->routes['*'][$routeKey]['redirect']);
631667
}
632668

633669
return false;
@@ -640,11 +676,16 @@ public function isRedirect(string $routeKey): bool
640676
*/
641677
public function getRedirectCode(string $routeKey): int
642678
{
643-
foreach ($this->routes['*'] as $name => $route) {
644-
// Named route?
645-
if ($name === $routeKey || key($route['route']) === $routeKey) {
646-
return $route['redirect'] ?? 0;
647-
}
679+
if (isset($this->routes['*'][$routeKey]['redirect'])) {
680+
return $this->routes['*'][$routeKey]['redirect'];
681+
}
682+
683+
// This logic is not used. Should be deprecated?
684+
$routeName = $this->routes['*'][$routeKey]['name'] ?? null;
685+
if ($routeName === $routeKey) {
686+
$routeKey = $this->routesNames['*'][$routeName];
687+
688+
return $this->routes['*'][$routeKey]['redirect'];
648689
}
649690

650691
return 0;
@@ -1050,7 +1091,7 @@ public function environment(string $env, Closure $callback): RouteCollectionInte
10501091
* // Equals 'path/$param1/$param2'
10511092
* reverseRoute('Controller::method', $param1, $param2);
10521093
*
1053-
* @param string $search Named route or Controller::method
1094+
* @param string $search Route name or Controller::method
10541095
* @param int|string ...$params One or more parameters to be passed to the route.
10551096
* The last parameter allows you to set the locale.
10561097
*
@@ -1059,9 +1100,11 @@ public function environment(string $env, Closure $callback): RouteCollectionInte
10591100
public function reverseRoute(string $search, ...$params)
10601101
{
10611102
// Named routes get higher priority.
1062-
foreach ($this->routes as $collection) {
1103+
foreach ($this->routesNames as $collection) {
10631104
if (array_key_exists($search, $collection)) {
1064-
return $this->buildReverseRoute(key($collection[$search]['route']), $params);
1105+
$routeKey = $collection[$search];
1106+
1107+
return $this->buildReverseRoute($routeKey, $params);
10651108
}
10661109
}
10671110

@@ -1077,9 +1120,8 @@ public function reverseRoute(string $search, ...$params)
10771120
// If it's not a named route, then loop over
10781121
// all routes to find a match.
10791122
foreach ($this->routes as $collection) {
1080-
foreach ($collection as $route) {
1081-
$routeKey = key($route['route']);
1082-
$to = $route['route'][$routeKey];
1123+
foreach ($collection as $routeKey => $route) {
1124+
$to = $route['handler'];
10831125

10841126
// ignore closures
10851127
if (! is_string($to)) {
@@ -1305,7 +1347,7 @@ protected function create(string $verb, string $from, $to, ?array $options = nul
13051347
}
13061348

13071349
// When redirecting to named route, $to is an array like `['zombies' => '\Zombies::index']`.
1308-
if (is_array($to) && count($to) === 2) {
1350+
if (is_array($to) && isset($to[0])) {
13091351
$to = $this->processArrayCallableSyntax($from, $to);
13101352
}
13111353

@@ -1386,20 +1428,21 @@ protected function create(string $verb, string $from, $to, ?array $options = nul
13861428
// routes should always be the "source of truth".
13871429
// this works only because discovered routes are added just prior
13881430
// to attempting to route the request.
1389-
$fromExists = dot_array_search('*.route.' . $routeKey, $this->routes[$verb] ?? []) !== null;
1390-
if ((isset($this->routes[$verb][$name]) || $fromExists) && ! $overwrite) {
1431+
$fromExists = isset($this->routes[$verb][$routeKey]);
1432+
if ((isset($this->routesNames[$verb][$name]) || $fromExists) && ! $overwrite) {
13911433
return;
13921434
}
13931435

1394-
$this->routes[$verb][$name] = [
1395-
'route' => [$routeKey => $to],
1436+
$this->routes[$verb][$routeKey] = [
1437+
'name' => $name,
1438+
'handler' => $to,
13961439
];
1397-
13981440
$this->routesOptions[$verb][$routeKey] = $options;
1441+
$this->routesNames[$verb][$name] = $routeKey;
13991442

14001443
// Is this a redirect?
14011444
if (isset($options['redirect']) && is_numeric($options['redirect'])) {
1402-
$this->routes['*'][$name]['redirect'] = $options['redirect'];
1445+
$this->routes['*'][$routeKey]['redirect'] = $options['redirect'];
14031446
}
14041447
}
14051448

@@ -1524,12 +1567,15 @@ private function determineCurrentSubdomain()
15241567
*/
15251568
public function resetRoutes()
15261569
{
1527-
$this->routes = ['*' => []];
1570+
$this->routes = $this->routesNames = ['*' => []];
15281571

15291572
foreach ($this->defaultHTTPMethods as $verb) {
1530-
$this->routes[$verb] = [];
1573+
$this->routes[$verb] = [];
1574+
$this->routesNames[$verb] = [];
15311575
}
15321576

1577+
$this->routesOptions = [];
1578+
15331579
$this->prioritizeDetected = false;
15341580
$this->didDiscover = false;
15351581
}
@@ -1595,9 +1641,8 @@ public function getRegisteredControllers(?string $verb = '*'): array
15951641

15961642
if ($verb === '*') {
15971643
foreach ($this->defaultHTTPMethods as $tmpVerb) {
1598-
foreach ($this->routes[$tmpVerb] as $route) {
1599-
$routeKey = key($route['route']);
1600-
$controller = $this->getControllerName($route['route'][$routeKey]);
1644+
foreach ($this->routes[$tmpVerb] as $routeKey => $route) {
1645+
$controller = $this->getControllerName($route['handler']);
16011646
if ($controller !== null) {
16021647
$controllers[] = $controller;
16031648
}

0 commit comments

Comments
 (0)