Пишем свой мини-роутер на PHP без фреймворка

2026-08-15 10:00:00

Не каждому проекту нужен Laravel или Symfony. Иногда достаточно 40 строк своего роутера — и этот блог, кстати, именно так и работает.

Идея

Роутер — это просто таблица соответствий «метод + путь» → «контроллер + метод». Плюс немного магии для параметров вида {slug}.

final class Router
{
    private array $routes = [];

    public function get(string $path, array $handler): void
    {
        $this->add('GET', $path, $handler);
    }

    public function post(string $path, array $handler): void
    {
        $this->add('POST', $path, $handler);
    }

    private function add(string $method, string $path, array $handler): void
    {
        $pattern = preg_replace('~\{[a-zA-Z_]+\}~', '([^/]+)', $path);
        $this->routes[$method][] = [
            'pattern' => '~^' . $pattern . '$~',
            'path' => $path,
            'handler' => $handler,
        ];
    }

    public function dispatch(string $method, string $uri): void
    {
        foreach ($this->routes[$method] ?? [] as $route) {
            if (preg_match($route['pattern'], $uri, $matches)) {
                array_shift($matches);
                [$class, $action] = $route['handler'];
                (new $class())->$action(['slug' => $matches[0] ?? null]);
                return;
            }
        }

        http_response_code(404);
        echo '404 Not Found';
    }
}

Почему это нормально

Для блога, лендинга или небольшого внутреннего сервиса такой роутер закрывает 100% потребностей. Фреймворк начинает окупаться, когда у вас десятки middleware, DI-контейнер и куча пакетов — до этого момента лишняя абстракция только замедляет разработку.

Что добавить, если вырастете

  • Middleware-цепочку для авторизации и CSRF
  • Именованные маршруты для генерации ссылок
  • Кэширование скомпилированных regex-паттернов

Но начинать с этого не стоит — YAGNI никто не отменял.