- Создано ядро 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
156 lines
4.2 KiB
PHP
156 lines
4.2 KiB
PHP
<?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']);
|
||
}
|
||
}
|
||
|