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