diff options
Diffstat (limited to 'src/app/Router.php')
| -rw-r--r-- | src/app/Router.php | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/app/Router.php b/src/app/Router.php new file mode 100644 index 0000000..9bfe09d --- /dev/null +++ b/src/app/Router.php @@ -0,0 +1,56 @@ +<?php + +declare(strict_types=1); +// Regex-based HTTP router that dispatches requests to controller methods. + +namespace App; + +class Router +{ + private array $routes = []; + + public function get(string $path, string $controller, string $method): void + { + $this->routes[] = ['GET', $path, $controller, $method]; + } + + public function post(string $path, string $controller, string $method): void + { + $this->routes[] = ['POST', $path, $controller, $method]; + } + + public function dispatch(): void + { + $requestMethod = $_SERVER['REQUEST_METHOD']; + $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); + $uri = rtrim($uri, '/') ?: '/'; + + foreach ($this->routes as [$method, $path, $controller, $action]) { + if ($method !== $requestMethod) { + continue; + } + + // Convert route placeholders to named regex capture groups. + // Example with route '/post/{id}' and request '/post/42': + // 1. preg_replace turns '{id}' into '(?P<id>[^/]+)' + // result: '#^/post/(?P<id>[^/]+)$#' + // 2. preg_match against '/post/42' produces: + // [0 => '/post/42', 'id' => '42', 1 => '42'] + // 3. array_filter keeps only string keys: ['id' => '42'] + // 4. PostController->show('42') is called + $pattern = preg_replace('#\{(\w+)\}#', '(?P<$1>[^/]+)', $path); + $pattern = '#^' . $pattern . '$#'; + + if (preg_match($pattern, $uri, $matches)) { + $params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY); + $controllerClass = "App\\Controllers\\$controller"; + $instance = new $controllerClass(); + $instance->$action(...array_values($params)); + return; + } + } + + http_response_code(404); + echo '404 Not Found'; + } +} |
