map('GET', $path, $handler); } public function post(string $path, callable $handler): void { $this->map('POST', $path, $handler); } public function patch(string $path, callable $handler): void { $this->map('PATCH', $path, $handler); } public function delete(string $path, callable $handler): void { $this->map('DELETE', $path, $handler); } public function dispatch(): void { $method = $this->request->method(); $path = $this->request->path(); foreach ($this->routes[$method] ?? [] as $route) { $pattern = preg_replace('#\{([a-zA-Z_][a-zA-Z0-9_]*)\}#', '(?P<$1>[^/]+)', $route['path']); $pattern = '#^' . $pattern . '$#'; if (!preg_match($pattern, $path, $matches)) { continue; } $params = array_filter($matches, static fn (string|int $key): bool => is_string($key), ARRAY_FILTER_USE_KEY); $route['handler']($this->request, $params); return; } Response::json(['message' => 'Route not found', 'path' => $path], 404); } private function map(string $method, string $path, callable $handler): void { $this->routes[$method][] = [ 'path' => rtrim($path, '/') ?: '/', 'handler' => $handler, ]; } }