routes[] = [ 'method' => strtoupper($method), 'route' => $route, 'controller' => $controller, 'action' => $action ]; return $this; } public function get(string $route, string $controller, string $action): self { return $this->add('GET', $route, $controller, $action); } public function post(string $route, string $controller, string $action): self { return $this->add('POST', $route, $controller, $action); } public function match(string $url, string $method): ?array { $method = strtoupper($method); $url = $this->removeQueryString($url); $url = trim($url, '/'); foreach ($this->routes as $route) { if ($route['method'] !== $method) { continue; } $pattern = $this->convertRouteToRegex($route['route']); if (preg_match($pattern, $url, $matches)) { $this->params = $this->extractParams($route['route'], $matches); return [ 'controller' => $route['controller'], 'action' => $route['action'], 'params' => $this->params ]; } } return null; } private function convertRouteToRegex(string $route): string { $route = trim($route, '/'); $pattern = preg_replace('/\{([a-zA-Z_]+)\}/', '([^/]+)', $route); return '#^' . $pattern . '$#'; } private function extractParams(string $route, array $matches): array { $params = []; preg_match_all('/\{([a-zA-Z_]+)\}/', $route, $paramNames); foreach ($paramNames[1] as $index => $name) { if (isset($matches[$index + 1])) { $params[$name] = $matches[$index + 1]; } } return $params; } private function removeQueryString(string $url): string { if ($pos = strpos($url, '?')) { $url = substr($url, 0, $pos); } return $url; } public function getParams(): array { return $this->params; } public function dispatch(string $url, string $method): void { $match = $this->match($url, $method); if ($match === null) { http_response_code(404); echo View::render('errors/404', ['url' => $url], 'main'); return; } $controllerClass = "App\\Controllers\\" . $match['controller']; $action = $match['action']; if (!class_exists($controllerClass)) { throw new \Exception("Контроллер {$controllerClass} не найден"); } $controller = new $controllerClass(); if (!method_exists($controller, $action)) { throw new \Exception("Метод {$action} не найден в контроллере {$controllerClass}"); } call_user_func_array([$controller, $action], $match['params']); } }