Skip to content

Commit e969f1d

Browse files
committed
perf: change RouteCollection::$routes structure
1 parent 0de7290 commit e969f1d

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
@@ -116,13 +116,16 @@ class RouteCollection implements RouteCollectionInterface
116116
*
117117
* [
118118
* verb => [
119-
* routeName => [
120-
* 'route' => [
121-
* routeKey(regex) => handler,
122-
* or routeKey(regex)(from) => [routeKey(regex)(to) => handler], // redirect
123-
* ],
119+
* routeKey(regex) => [
120+
* 'name' => routeName
121+
* 'handler' => handler,
122+
* ],
123+
* // redirect route
124+
* or routeKey(regex)(from) => [
125+
* 'name' => routeName
126+
* 'handler' => [routeKey(regex)(to) => handler],
124127
* 'redirect' => statusCode,
125-
* ]
128+
* ],
126129
* ],
127130
* ]
128131
*/
@@ -139,6 +142,30 @@ class RouteCollection implements RouteCollectionInterface
139142
'cli' => [],
140143
];
141144

145+
/**
146+
* Array of routes names
147+
*
148+
* @var array
149+
*
150+
* [
151+
* verb => [
152+
* routeName => routeKey(regex)
153+
* ],
154+
* ]
155+
*/
156+
protected $routesNames = [
157+
'*' => [],
158+
'options' => [],
159+
'get' => [],
160+
'head' => [],
161+
'post' => [],
162+
'put' => [],
163+
'delete' => [],
164+
'trace' => [],
165+
'connect' => [],
166+
'cli' => [],
167+
];
168+
142169
/**
143170
* Array of routes options
144171
*
@@ -533,9 +560,8 @@ public function getRoutes(?string $verb = null): array
533560
// before any of the generic, "add" routes.
534561
$collection = $this->routes[$verb] + ($this->routes['*'] ?? []);
535562

536-
foreach ($collection as $r) {
537-
$key = key($r['route']);
538-
$routes[$key] = $r['route'][$key];
563+
foreach ($collection as $routeKey => $r) {
564+
$routes[$routeKey] = $r['handler'];
539565
}
540566
}
541567

@@ -632,11 +658,16 @@ public function add(string $from, $to, ?array $options = null): RouteCollectionI
632658
public function addRedirect(string $from, string $to, int $status = 302)
633659
{
634660
// Use the named route's pattern if this is a named route.
635-
if (array_key_exists($to, $this->routes['*'])) {
636-
$redirectTo = $this->routes['*'][$to]['route'];
637-
} elseif (array_key_exists($to, $this->routes['get'])) {
638-
$redirectTo = $this->routes['get'][$to]['route'];
661+
if (array_key_exists($to, $this->routesNames['*'])) {
662+
$routeName = $to;
663+
$routeKey = $this->routesNames['*'][$routeName];
664+
$redirectTo = [$routeKey => $this->routes['*'][$routeKey]['handler']];
665+
} elseif (array_key_exists($to, $this->routesNames['get'])) {
666+
$routeName = $to;
667+
$routeKey = $this->routesNames['get'][$routeName];
668+
$redirectTo = [$routeKey => $this->routes['get'][$routeKey]['handler']];
639669
} else {
670+
// The named route is not found.
640671
$redirectTo = $to;
641672
}
642673

@@ -652,11 +683,16 @@ public function addRedirect(string $from, string $to, int $status = 302)
652683
*/
653684
public function isRedirect(string $routeKey): bool
654685
{
655-
foreach ($this->routes['*'] as $name => $route) {
656-
// Named route?
657-
if ($name === $routeKey || key($route['route']) === $routeKey) {
658-
return isset($route['redirect']) && is_numeric($route['redirect']);
659-
}
686+
if (isset($this->routes['*'][$routeKey]['redirect'])) {
687+
return true;
688+
}
689+
690+
// This logic is not used. Should be deprecated?
691+
$routeName = $this->routes['*'][$routeKey]['name'] ?? null;
692+
if ($routeName === $routeKey) {
693+
$routeKey = $this->routesNames['*'][$routeName];
694+
695+
return isset($this->routes['*'][$routeKey]['redirect']);
660696
}
661697

662698
return false;
@@ -669,11 +705,16 @@ public function isRedirect(string $routeKey): bool
669705
*/
670706
public function getRedirectCode(string $routeKey): int
671707
{
672-
foreach ($this->routes['*'] as $name => $route) {
673-
// Named route?
674-
if ($name === $routeKey || key($route['route']) === $routeKey) {
675-
return $route['redirect'] ?? 0;
676-
}
708+
if (isset($this->routes['*'][$routeKey]['redirect'])) {
709+
return $this->routes['*'][$routeKey]['redirect'];
710+
}
711+
712+
// This logic is not used. Should be deprecated?
713+
$routeName = $this->routes['*'][$routeKey]['name'] ?? null;
714+
if ($routeName === $routeKey) {
715+
$routeKey = $this->routesNames['*'][$routeName];
716+
717+
return $this->routes['*'][$routeKey]['redirect'];
677718
}
678719

679720
return 0;
@@ -1088,9 +1129,11 @@ public function environment(string $env, Closure $callback): RouteCollectionInte
10881129
public function reverseRoute(string $search, ...$params)
10891130
{
10901131
// Named routes get higher priority.
1091-
foreach ($this->routes as $collection) {
1132+
foreach ($this->routesNames as $collection) {
10921133
if (array_key_exists($search, $collection)) {
1093-
return $this->buildReverseRoute(key($collection[$search]['route']), $params);
1134+
$routeKey = $collection[$search];
1135+
1136+
return $this->buildReverseRoute($routeKey, $params);
10941137
}
10951138
}
10961139

@@ -1106,9 +1149,8 @@ public function reverseRoute(string $search, ...$params)
11061149
// If it's not a named route, then loop over
11071150
// all routes to find a match.
11081151
foreach ($this->routes as $collection) {
1109-
foreach ($collection as $route) {
1110-
$routeKey = key($route['route']);
1111-
$to = $route['route'][$routeKey];
1152+
foreach ($collection as $routeKey => $route) {
1153+
$to = $route['handler'];
11121154

11131155
// ignore closures
11141156
if (! is_string($to)) {
@@ -1334,7 +1376,7 @@ protected function create(string $verb, string $from, $to, ?array $options = nul
13341376
}
13351377

13361378
// When redirecting to named route, $to is an array like `['zombies' => '\Zombies::index']`.
1337-
if (is_array($to) && count($to) === 2) {
1379+
if (is_array($to) && isset($to[0])) {
13381380
$to = $this->processArrayCallableSyntax($from, $to);
13391381
}
13401382

@@ -1414,20 +1456,21 @@ protected function create(string $verb, string $from, $to, ?array $options = nul
14141456
// routes should always be the "source of truth".
14151457
// this works only because discovered routes are added just prior
14161458
// to attempting to route the request.
1417-
$fromExists = dot_array_search('*.route.' . $routeKey, $this->routes[$verb] ?? []) !== null;
1418-
if ((isset($this->routes[$verb][$name]) || $fromExists) && ! $overwrite) {
1459+
$fromExists = isset($this->routes[$verb][$routeKey]);
1460+
if ((isset($this->routesNames[$verb][$name]) || $fromExists) && ! $overwrite) {
14191461
return;
14201462
}
14211463

1422-
$this->routes[$verb][$name] = [
1423-
'route' => [$routeKey => $to],
1464+
$this->routes[$verb][$routeKey] = [
1465+
'name' => $name,
1466+
'handler' => $to,
14241467
];
1425-
14261468
$this->routesOptions[$verb][$routeKey] = $options;
1469+
$this->routesNames[$verb][$name] = $routeKey;
14271470

14281471
// Is this a redirect?
14291472
if (isset($options['redirect']) && is_numeric($options['redirect'])) {
1430-
$this->routes['*'][$name]['redirect'] = $options['redirect'];
1473+
$this->routes['*'][$routeKey]['redirect'] = $options['redirect'];
14311474
}
14321475
}
14331476

@@ -1568,12 +1611,15 @@ private function determineCurrentSubdomain()
15681611
*/
15691612
public function resetRoutes()
15701613
{
1571-
$this->routes = ['*' => []];
1614+
$this->routes = $this->routesNames = ['*' => []];
15721615

15731616
foreach ($this->defaultHTTPMethods as $verb) {
1574-
$this->routes[$verb] = [];
1617+
$this->routes[$verb] = [];
1618+
$this->routesNames[$verb] = [];
15751619
}
15761620

1621+
$this->routesOptions = [];
1622+
15771623
$this->prioritizeDetected = false;
15781624
$this->didDiscover = false;
15791625
}
@@ -1639,9 +1685,8 @@ public function getRegisteredControllers(?string $verb = '*'): array
16391685

16401686
if ($verb === '*') {
16411687
foreach ($this->defaultHTTPMethods as $tmpVerb) {
1642-
foreach ($this->routes[$tmpVerb] as $route) {
1643-
$routeKey = key($route['route']);
1644-
$controller = $this->getControllerName($route['route'][$routeKey]);
1688+
foreach ($this->routes[$tmpVerb] as $routeKey => $route) {
1689+
$controller = $this->getControllerName($route['handler']);
16451690
if ($controller !== null) {
16461691
$controllers[] = $controller;
16471692
}

0 commit comments

Comments
 (0)