Migrate some improvements to the router.

This commit is contained in:
Sky Johnson 2024-12-14 18:44:33 -06:00
parent 02533addb4
commit 3bc53c1a31
3 changed files with 13 additions and 31 deletions

View File

@ -45,7 +45,7 @@ $r->form('/babblebox', 'babblebox');
// [code, handler, params, middleware] // [code, handler, params, middleware]
$l = $r->lookup($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']); $l = $r->lookup($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
if ($l['code'] !== 200) exit("Error: {$l['code']}"); if (is_int($l)) exit("Error: $l");
if (!empty($l['middleware'])) foreach ($l['middleware'] as $middleware) $middleware(); if (!empty($l['middleware'])) foreach ($l['middleware'] as $middleware) $middleware();
$l['handler'](...$l['params'] ?? []); $l['handler'](...$l['params'] ?? []);

View File

@ -24,7 +24,6 @@ function move()
$town = get_town_by_xy($longitude, $latitude); $town = get_town_by_xy($longitude, $latitude);
if ($town !== false) { if ($town !== false) {
require_once __DIR__ . '/towns.php';
Towns\travelto($town['id'], false); Towns\travelto($town['id'], false);
return; return;
} }

View File

@ -33,23 +33,20 @@ class Router
$this->validateMethod($method); $this->validateMethod($method);
$this->validateRoute($route); $this->validateRoute($route);
// Expand the route into segments and make dynamic segments into a common placeholder $segments = $route === '/' ? [''] : explode('/', trim($route, '/'));
$segments = array_map(function($segment) {
return str_starts_with($segment, ':') ? ':x' : $segment;
}, explode('/', trim($route, '/')));
// Push each segment into the routes array as a node, except if this is the root node
$node = &$this->routes; $node = &$this->routes;
foreach ($segments as $segment) { foreach ($segments as $segment) {
// skip an empty segment, which allows us to register handlers for the root node $segment = str_starts_with($segment, ':') ? ':x' : $segment;
if ($segment === '') continue; if ($segment === '') continue;
$node = &$node[$segment]; // build the node tree as we go $node = &$node[$segment];
} }
// Add the handler to the last node $node[$method] = [
$node[$method] = ['handler' => $handler, 'middleware' => []]; 'handler' => $handler,
'middleware' => []
];
// Store a reference to the node so we can add middleware to it.
$this->last_inserted_node = &$node[$method]; $this->last_inserted_node = &$node[$method];
return $this; return $this;
@ -62,44 +59,30 @@ class Router
* *
* @return array ['code', 'handler', 'params'] * @return array ['code', 'handler', 'params']
*/ */
public function lookup(string $method, string $uri): array public function lookup(string $method, string $uri): array|int
{ {
// node is a reference to our current location in the node tree
$node = $this->routes; $node = $this->routes;
// params will hold any dynamic segments we find
$params = []; $params = [];
// if the URI is just a slash, we can return the handler for the root node if ($uri === '/') return $node[$method] ?? 405;
if ($uri === '/') {
return isset($node[$method])
? ['code' => 200, 'handler' => $node[$method]['handler']]
: ['code' => 405];
}
// We'll split up the URI into segments and traverse the node tree
foreach (explode('/', trim($uri, '/')) as $segment) { foreach (explode('/', trim($uri, '/')) as $segment) {
// if there is a node for this segment, move to it
if (isset($node[$segment])) { if (isset($node[$segment])) {
$node = $node[$segment]; $node = $node[$segment];
continue; continue;
} }
// if there is a dynamic segment, move to it and store the value
if (isset($node[':x'])) { if (isset($node[':x'])) {
$params[] = $segment; $params[] = $segment;
$node = $node[':x']; $node = $node[':x'];
continue; continue;
} }
// if we can't find a node for this segment, return 404 return 404;
return ['code' => 404];
} }
// if we found a handler for the method, return it and any params. if not, return a 405 $node[$method]['params'] = $params;
return isset($node[$method]) return $node[$method] ?? 405;
? ['code' => 200, 'handler' => $node[$method]['handler'], 'params' => $params ?? [], 'middleware' => $node[$method]['middleware']]
: ['code' => 405];
} }
/** /**