Маршрутизация (роутинг)

В JohnCMS маршрутизация построена на Johncms\Router\RouteCollection и Symfony Routing.

Эта страница описывает текущий подход: как объявлять маршруты, как подключать middleware, какие бывают обработчики и как происходит dispatch.

Где описываются маршруты

Маршруты загружаются в следующем порядке:

  1. config/routes.php — глобальные/системные маршруты (зарезервирован для ядра)

  2. modules/{name}/config/routes.php — маршруты каждого модуля (подхватываются автоматически)

  3. config/routes.local.php — переопределения для конкретного проекта (наивысший приоритет, устарел)

Каждый модуль регистрирует свои маршруты в config/routes.php внутри папки модуля. Файл подхватывается автоматически — вручную подключать его не нужно.

config/routes.local.php устарел и будет удалён в будущих версиях. Если у вас есть маршруты в этом файле, перенесите их в modules/{name}/config/routes.php.

Базовый пример маршрута

Файл modules/{name}/config/routes.php должен возвращать callable:

<?php

declare(strict_types=1);

use Johncms\Router\RouteCollection;
use Johncms\System\Users\User;

return static function (RouteCollection $router, User $user): void {
    $router->get('/contacts', 'modules/contacts/index.php');
    $router->map(['GET', 'POST'], '/feedback', 'modules/feedback/index.php');
};

Параметр $user доступен для регистрации маршрутов, зависящих от состояния пользователя:

Параметры и ограничения

Маршрут может содержать параметры и ограничения через requirements():

Также поддерживаются пресеты в пути:

  • {id:number}

  • {article_code:slug}

  • {category:path}

Примеры можно посмотреть в файлах modules/*/config/routes.php.

Middleware на маршрутах

Middleware — это промежуточный обработчик между совпавшим маршрутом и его handler. Он получает Request, может выполнить проверку/подготовку и передать управление дальше через $next($request).

Обычно middleware используют для:

  • проверки доступа (права, авторизация, владение ресурсом)

  • валидации обязательных условий перед действием

  • логирования и других сквозных задач

Middleware для конкретного маршрута

Добавление middleware к одному маршруту:

Можно указывать несколько middleware, они будут вызваны по порядку добавления.

Middleware для группы/коллекции маршрутов

Можно добавить middleware сразу на коллекцию (например, в группе):

Такой middleware будет применяться ко всем маршрутам внутри этой коллекции.

Допустимые типы middleware

Middleware может быть:

  • классом (получается из контейнера), реализующим Johncms\Router\MiddlewareInterface

  • callable

Контракт middleware для класса:

Пример класса middleware:

Пример callable middleware:

Порядок выполнения

При обработке совпавшего маршрута выполняется цепочка:

  1. middleware коллекции/группы

  2. middleware самого маршрута

  3. handler маршрута

Если middleware не вызывает $next($request), цепочка останавливается и handler не будет вызван.

Какие обработчики поддерживаются

В маршруте можно указать:

  1. Строку с путем legacy-файла ('modules/contacts/index.php')

  2. Invokable-контроллер (SomeController::class с __invoke())

  3. Массив [ControllerClass::class, 'method']

Это обрабатывается в index.php через ActionInvoker и MiddlewareDispatcher.

Как работает dispatch

Схема обработки запроса:

  1. URI нормализуется в index.php

  2. SymfonyRouteMatcher::dispatch() пытается сопоставить маршрут

  3. При FOUND:

    • route params кладутся в request

    • запускается цепочка middleware

    • вызывается handler

  4. При METHOD_NOT_ALLOWED возвращается 405 Method Not Allowed

  5. При NOT_FOUND вызывается pageNotFound()

Типовые ошибки

404 Not Found

Причины:

  • путь не совпадает с шаблоном маршрута

  • route params не прошли requirements

  • маршрут не зарегистрирован в modules/{name}/config/routes.php или config/routes.local.php

405 Method Not Allowed

Причина:

  • URL найден, но HTTP-метод не разрешен для маршрута (например, POST вместо GET).

Ошибка middleware

Причины:

  • middleware-класс не зарегистрирован в контейнере

  • middleware не callable и не реализует MiddlewareInterface

В этом случае MiddlewareDispatcher выбросит InvalidArgumentException.

См. также

Последнее обновление

Это было полезно?