Rudra FrameworkRudra Framework

Жизненный цикл запроса в Rudra

Когда Rudra получает HTTP-запрос, он проходит через четыре фазы инициализации и выполнения. Понимание этого цикла критически важно для эффективной разработки и отладки.


1. Инициализация ядра (Ship)

Первым делом вызывается метод shipInit() из App\Ship\ShipController.

Что происходит:

  • Останавливается замер времени в debugbar (если environment = development);
  • Регистрируются глобальные события через Dispatcher::addListener() и Dispatcher::attachObserver().

Этот этап выполняется один раз за запрос, до маршрутизации.


2. Определение контейнера и маршрута

Rudra:

  • Анализирует URL;
  • Сопоставляет его с маршрутами (из атрибутов #[Routing] или routes.php);
  • Определяет, к какому контейнеру относится контроллер (например, App\Containers\Web\Controller\IndexController → контейнер web).

3. Инициализация контейнера

При первом обращении к контроллеру из контейнера вызывается containerInit() из его базового класса (например, WebController).

Что происходит:

  • Загружается config.php контейнера;
  • Регистрируются локальные контракты и сервисы в DI-контейнер
Rudra::binding()->set($config['contracts']);
Rudra::waiting()->set($config['services']);

Настраивается шаблонизатор:

View::setup(dirname(__DIR__) . "/Web/UI/tmpl", "Web_");
  • Устанавливаются глобальные данные (меню, заголовок и т.д.).

✅Этот этап выполняется один раз на контейнер за запрос.


4. Выполнение контроллера

Rudra вызывает метод-действие, помеченный #[Routing].

Что происходит:

  1. Если у метода есть параметры — они заполняются:
    • из URL (:id, :slug);
    • через DI (автоматическое внедрение зависимостей).
  2. Запускаются before-middleware (если есть #[Middleware]);
  3. Выполняется тело метода;
  4. Запускаются after-middleware (если есть #[AfterMiddleware]);
  5. Результат выводится через render(), json(), redirect() и т.д.

Порядок параметров в методе действия

⚠️В методах контроллеров параметры DI (объекты) должны идти строго перед URL-параметрами:

// ✅ Правильно
public function show(User $user, int $id, string $slug): void
{
    // $user — внедрён через DI
    // $id, $slug — из маршрута :id/:slug
}
// ❌ Неправильно
public function show(int $id, User $user, string $slug): void
{
    // Rudra не сможет определить, какой аргумент откуда брать
}

ℹ️Это требование связано с тем, что Rudra сначала разрешает все типизированные зависимости через DI, а затем подставляет скалярные значения из URL в оставшиеся позиции.


Схема жизненного цикла

HTTP-запрос
    ↓
App\Ship\ShipController::shipInit()
    ↓
Определение контейнера и маршрута
    ↓
{Container}Controller::containerInit()
    ↓
Before-middleware → Контроллер → After-middleware
    ↓
HTTP-ответ

Советы

  • Используйте shipInit() для глобальных подписок на события.
  • Используйте containerInit() для настройки модуля (сервисы, шаблоны, меню).
  • Не кладите логику в containerInit() — только инициализацию.
  • Все тяжёлые операции — в сервисах, а не в контроллерах.