Skip to content

Commit 719b11c

Browse files
committed
perf: change RouteCollection::$routes structure
1 parent 12c79f6 commit 719b11c

File tree

1 file changed

+85
-40
lines changed

1 file changed

+85
-40
lines changed

system/Router/RouteCollection.php

Lines changed: 85 additions & 40 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;
@@ -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

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

1393-
$this->routes[$verb][$name] = [
1394-
'route' => [$routeKey => $to],
1435+
$this->routes[$verb][$routeKey] = [
1436+
'name' => $name,
1437+
'handler' => $to,
13951438
];
1396-
13971439
$this->routesOptions[$verb][$routeKey] = $options;
1440+
$this->routesNames[$verb][$name] = $routeKey;
13981441

13991442
// Is this a redirect?
14001443
if (isset($options['redirect']) && is_numeric($options['redirect'])) {
1401-
$this->routes['*'][$name]['redirect'] = $options['redirect'];
1444+
$this->routes['*'][$routeKey]['redirect'] = $options['redirect'];
14021445
}
14031446
}
14041447

@@ -1539,12 +1582,15 @@ private function determineCurrentSubdomain()
15391582
*/
15401583
public function resetRoutes()
15411584
{
1542-
$this->routes = ['*' => []];
1585+
$this->routes = $this->routesNames = ['*' => []];
15431586

15441587
foreach ($this->defaultHTTPMethods as $verb) {
1545-
$this->routes[$verb] = [];
1588+
$this->routes[$verb] = [];
1589+
$this->routesNames[$verb] = [];
15461590
}
15471591

1592+
$this->routesOptions = [];
1593+
15481594
$this->prioritizeDetected = false;
15491595
$this->didDiscover = false;
15501596
}
@@ -1610,9 +1656,8 @@ public function getRegisteredControllers(?string $verb = '*'): array
16101656

16111657
if ($verb === '*') {
16121658
foreach ($this->defaultHTTPMethods as $tmpVerb) {
1613-
foreach ($this->routes[$tmpVerb] as $route) {
1614-
$routeKey = key($route['route']);
1615-
$controller = $this->getControllerName($route['route'][$routeKey]);
1659+
foreach ($this->routes[$tmpVerb] as $routeKey => $route) {
1660+
$controller = $this->getControllerName($route['handler']);
16161661
if ($controller !== null) {
16171662
$controllers[] = $controller;
16181663
}

0 commit comments

Comments
 (0)