Files
web_work/app/Core/Router.php
2026-01-03 18:59:56 +03:00

118 lines
3.2 KiB
PHP

<?php
namespace App\Core;
class Router
{
private array $routes = [];
private array $params = [];
public function add(string $method, string $route, string $controller, string $action): self
{
$this->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']);
}
}