Adapt uri parser to accept simpler, generic parameter placeholders

This commit is contained in:
Skylear 2021-07-15 14:26:00 -05:00
parent 087ddabfff
commit aa32226435

View File

@ -12,14 +12,14 @@ class Router
* A quick static function to register a route in the router. Used by the shorthand methods as well. * A quick static function to register a route in the router. Used by the shorthand methods as well.
* @param string $route The path to be used as the route. * @param string $route The path to be used as the route.
* @param callable|string $action Either a callable to be executed, or a string reference to a method. * @param callable|string $action Either a callable to be executed, or a string reference to a method.
* @param string $method The HTTP verb this route services. * @param string|array $methods The HTTP verb(s) this route accepts.
*/ */
public static function add(string $route, callable|string $action, string $method = 'GET') public static function add(string $route, callable|string $action, string|array $methods = 'GET')
{ {
self::$routes[] = [ self::$routes[] = [
'route' => $route, 'route' => $route,
'action' => $action, 'action' => $action,
'method' => $method 'methods' => $methods
]; ];
} }
@ -48,54 +48,59 @@ class Router
self::$methodNotAllowed = $action; self::$methodNotAllowed = $action;
} }
public static function run(string $basePath = '', bool $caseMatters = false, bool $multimatch = false) private static function tokenize(string $uri)
{
return preg_replace('/(?:{([A-Za-z]+)})+/', '([\w]+)', $uri);
}
public static function run(string $basePath = '', bool $multimatch = false)
{ {
$basePath = rtrim($basePath, '/'); $basePath = rtrim($basePath, '/');
$path = rtrim(parse_url($_SERVER['REQUEST_URI']), '/'); $uri = parse_url($_SERVER['REQUEST_URI'])['path'];
$method = $_SERVER['REQUEST_METHOD']; $method = $_SERVER['REQUEST_METHOD'];
$path = urldecode(rtrim($uri, '/'));
$path = urldecode($path); // If the path is empty (no slash in URI) place one to satisfy the root route ('/')
if (empty($path)) {
$path = '/';
}
$pathMatchFound = false; $pathMatchFound = false;
$routeMatchFound = false; $routeMatchFound = false;
// Begin looking through routes
foreach (self::$routes as $route) { foreach (self::$routes as $route) {
if ($basePath != '' && $basePath != '/') { if ($basePath != '' && $basePath != '/') {
$route['route'] = '('.$basePath.')'.$route['route']; $route['route'] = $basePath.$route['route'];
} }
// Add string start and end automatically // Prepare route by tokenizing.
$route['route'] = '^'.$route['route'].'$'; $tokenized = '#^'.self::tokenize($route['route']).'$#u';
die('#'.$route['route'].'#'.($caseMatters ? '' : 'i').'u'); // If the tokenized route matches the current path...
if (preg_match($tokenized, $path, $matches)) {
// Check path match
if (preg_match('#'.$route['route'].'#'.($caseMatters ? '' : 'i').'u', $path, $matches)) {
$pathMatchFound = true; $pathMatchFound = true;
// Cast allowed method to array if it's not one already, then run through all methods // Run through the route's accepted method(s)
foreach ((array) $route['method'] as $allowedMethod) { foreach ((array) $route['methods'] as $allowedMethod) {
// Check method match // See if the current request method matches
if (strtolower($method) == strtolower($allowedMethod)) { if (strtolower($method) == strtolower($allowedMethod)) {
array_shift($matches); // Always remove first element. This contains the whole string array_shift($matches); // Remove the first match - always contains the full url
if ($basePath != '' && $basePath != '/') {
array_shift($matches); // Remove basepath
}
// If we're successful at calling the route's action, echo the result
if ($return = call_user_func_array($route['action'], $matches)) { if ($return = call_user_func_array($route['action'], $matches)) {
echo $return; echo $return;
} }
$routeMatchFound = true; $routeMatchFound = true;
// Do not check other routes // Do not check other routes.
break; break;
} }
} }
} }
// Break the loop if the first found route is a match // Break the loop if the first found route is a match.
if($routeMatchFound && !$multimatch) { if($routeMatchFound && !$multimatch) {
break; break;
} }
@ -106,13 +111,15 @@ class Router
// But a matching path exists // But a matching path exists
if ($pathMatchFound) { if ($pathMatchFound) {
if (self::$methodNotAllowed) { if (self::$methodNotAllowed) {
die('Method not allowed'); call_user_func_array(self::$methodNotAllowed, Array($path, $method));
//call_user_func_array(self::$methodNotAllowed, Array($path, $method)); } else {
die('405');
} }
} else { } else {
if (self::$pathNotFound) { if (self::$pathNotFound) {
die('Path not found'); call_user_func_array(self::$pathNotFound, Array($path));
//call_user_func_array(self::$pathNotFound, Array($path)); } else {
die('404');
} }
} }
} }