Files
web_work/app/Core/Router.php
kirill.khorkov d2c15ec37f [MVC] Полная миграция на MVC архитектуру
- Создано ядро MVC: App, Router, Controller, Model, View, Database
- Созданы модели: User, Product, Category, Cart, Order
- Созданы контроллеры: Home, Auth, Product, Cart, Order, Page, Admin
- Созданы layouts и partials для представлений
- Добавлены все views для страниц
- Настроена маршрутизация с чистыми URL
- Обновлена конфигурация Docker и Apache для mod_rewrite
- Добавлена единая точка входа public/index.php
2026-01-03 11:48:14 +03:00

156 lines
4.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Core;
/**
* Router - маршрутизатор запросов
*/
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;
}
/**
* GET маршрут
*/
public function get(string $route, string $controller, string $action): self
{
return $this->add('GET', $route, $controller, $action);
}
/**
* POST маршрут
*/
public function post(string $route, string $controller, string $action): self
{
return $this->add('POST', $route, $controller, $action);
}
/**
* Найти маршрут по URL и методу
*/
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)) {
// Извлекаем параметры из URL
$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, '/');
// Заменяем {param} на regex группу
$pattern = preg_replace('/\{([a-zA-Z_]+)\}/', '([^/]+)', $route);
return '#^' . $pattern . '$#';
}
/**
* Извлечь параметры из совпадений
*/
private function extractParams(string $route, array $matches): array
{
$params = [];
// Находим все {param} в маршруте
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;
}
/**
* Удалить query string из URL
*/
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']);
}
}