2026-08-20 22:37:44 +03:00
# Обзор архитектуры
## Тип проекта
Структурированный монолит PHP с модульным дополнительным слоем.
- Никакого DDD, никакой гексагональности, никакой чистой архитектуры — намеренно.
2026-08-21 16:31:01 +03:00
- Split by context with minimal abstractions: `Controller → Service → Repository` .
2026-08-27 18:07:43 +03:00
- Два артефакта сборки из одной кодовой базы: **главный** (полная панель) и **фунт** (подмножество load balancer).
2026-08-20 22:37:44 +03:00
---
2026-08-27 18:07:43 +03:00
## Исходное дерево
2026-08-20 22:37:44 +03:00
|Путь|Роль|
| ---- | ---- |
2026-08-27 18:07:43 +03:00
| `src/Core/` |Примитивы фреймворка: Контейнер DI, события, HTTP/маршрутизатор, конфигурация, авторизация, ведение журнала|
2026-08-21 16:31:01 +03:00
| `src/Domain/` |Бизнес-контексты: Поток, VOD, линия, пользователь, сервер, безопасность и т.д.|
2026-08-27 18:07:43 +03:00
| `src/Infrastructure/` |Внешние адаптеры: `DatabaseFactory` , считыватели кэша, Redis, TMDb|
| `src/Streaming/` |Потоковая подсистема: bootstrap, аутентификация, доставка, балансировщик, защита|
2026-08-20 22:37:44 +03:00
| `src/Modules/` |Дополнительный слой расширения — загружается с помощью `ModuleLoader` |
| `src/Public/` |Передний контроллер, маршрутизатор, контроллеры, представления, ресурсы|
| `src/Cli/` |Консольные команды и точки входа в cron|
2026-08-21 16:31:01 +03:00
| `src/Ministra/` | Stalker Portal — in core; served at `/home/xc_vm/Ministra` |
2026-08-20 22:37:44 +03:00
---
## Модель времени выполнения
Зависимости перетекают друг в друга — модули могут использовать ядро и домен, но никогда наоборот.
```
Public/index.php
2026-08-27 18:07:43 +03:00
└── XC_Bootstrap::boot(BootContext::Admin)
2026-08-20 22:37:44 +03:00
└── ServiceContainer (DI)
├── EventDispatcher (PSR-14)
├── ModuleLoader → loadAll() → bootAll()
└── Router → dispatch()
```
2026-08-27 18:07:43 +03:00
Классы домена и модуля принимают **нет** и `$db` в своем конструкторе. Они
`use \XcVm\Infrastructure\Database\DatabaseAware` и вызываем `self::db()` , который лениво
устраняет общее соединение. `bootstrap.php::wireDomainDatabase()` устанавливает это соединение
**однажды** для каждой загрузки (через `DatabaseAware::setDb()` ) — нет проводки для каждого класса и нет
`global $db` в пути веб-запроса.
2026-08-20 22:37:44 +03:00
---
## Модульная система
Модули представляют собой изолированные каталоги под `src/Modules/` с манифестом `module.json`
2026-08-27 18:07:43 +03:00
и класс, расширяющий `BaseModule` . Полную справочную информацию (и связанные страницы о жизненном цикле / точках расширения) смотрите в [Разработка модуля ](module-authoring.md ).
2026-08-20 22:37:44 +03:00
```
src/Modules/my-module/
├── module.json # metadata
├── MyModuleModule.php # extends BaseModule, namespace XcVm\Module\MyModule
└── ...
```
---
## Контексты начальной загрузки
Четыре контекста определяют, какие подсистемы инициализируются. Смотрите [Контексты начальной загрузки ](bootstrap-contexts.md ).
|Контекст|Используется для|
| ------- | -------- |
2026-08-27 18:07:43 +03:00
| `BootContext::Minimal` |Скрипты, которым нужны только пути / конфигурация|
| `BootContext::Cli` |Задания Cron и команды CLI|
| `BootContext::Stream` |Конечные точки потоковой передачи|
| `BootContext::Admin` |Панель администратора/реселлера|
2026-08-20 22:37:44 +03:00
---
## Варианты сборки (ОСНОВНАЯ и LB)
| |главный|фунт|
| --- | ---- | -- |
|Панель администратора|✅|❌|
|Потоковый|✅|✅|
|Модульная система|✅|подмножество|
2026-08-27 18:07:43 +03:00
Управляется перечислением `ServerEnvironment` и каждым полем `module.json` `environment`
(`main` / `lb` / `any` ). At boot, `ModuleLoader::getCurrentEnvironment()` resolves the node's
окружение из константы `SERVER_TYPE` (`'lb'` → `ServerEnvironment::LoadBalancer` , иначе
`ServerEnvironment::Main` ); модуль, у которого `environment` не соответствует узлу, пропускается, поэтому
LB получает **подмножество** модулей.
2026-08-20 22:37:44 +03:00
---
## Ключевые моменты расширения
|Механизм|Как использовать|
| --------- | ---------- |
2026-08-27 18:07:43 +03:00
|События PSR-14|`EventDispatcher::listen()` / `#[ListensTo]` — смотрите [Система событий ](event-system.md )|
|Оформление сервиса|`$container->decorate('id', callable, priority)` — смотрите [Точки расширения модуля ](module-extension-points.md#di-container-and-service-decoration )|
|Потоковое промежуточное программное обеспечение|Реализовать `StreamMiddlewareProviderInterface` — см. [Точки расширения модуля ](module-extension-points.md#stream-middleware )|
|Записи Cron|`getCronEntries()` в классе module — смотрите [Точки расширения модуля ](module-extension-points.md#cron-task )|
|Миграции баз данных|`MigratableInterface::getMigrations()` — смотрите [Точки расширения модуля ](module-extension-points.md#versioned-migrations-migratableinterface )|
2026-08-20 22:37:44 +03:00
---
## Правила для участников
1. Модули не должны изменять основные файлы.
2026-08-21 16:31:01 +03:00
2. Никаких `eval` , исправлений ошибок или замены файлов во время выполнения.
2026-08-20 22:37:44 +03:00
3. Любой модуль можно отключить с помощью `config/modules.php` , не прикасаясь к ядру.
4. Защищенные сервисы (`db` , `settings` , `config` , `auth` ) не могут быть оформлены.
5. Синхронизируйте документы EN и RU в одном и том же коммите.