besnovatyj/yii2-cms-modman
Composer 安装命令:
composer require besnovatyj/yii2-cms-modman
包简介
Система управления модулями Yii2 CMS (compile-not-patch): discovery, реестр состояния, компиляция производных конфигов, lifecycle установки/удаления модулей.
README 文档
README
Система управления модулями CMS на принципе compile-not-patch: состояние модулей декларативно и единично (реестр), а вся Yii-конфигурация — производная и компилируется заново. Модуль на стадии тестирования.
Пришла на смену прежнему патч-based modman, который сохранён как образец в app/modules/modman_b
(нерабочий, для сверки). Артефакты пишутся в канонические пути конфигурации приложения — без
суффиксов и аддитивных слияний.
- Идея и слои — ARCHITECTURE.md
- Пошаговый трекер и журнал решений — plan.md
- Сравнение «патч-modman → modman» — таблица в ARCHITECTURE.md §12
Карта каталога
catalog/ ModuleManifest + value-объекты, discovery (Filesystem/Composer), ManifestFactory,
PackageCatalog, InvalidModule, маркер CmsMarker/CmsKind (extra.bescms)
registry/ ModuleStatus, Version, ModuleState, ModuleRegistry (атомарный lock-файл — источник истины)
compiler/ AtomicWriter, ConfigCompiler (чистая компиляция), MenuCompiler, ArtifactPaths
deps/ SemverConstraint, DependencyGraph, DependencyResolver (прямые + обратные зависимости)
migration/ MigrationOwnershipRepository, ModuleMigrationRunner (учёт владения, pending-only update)
lifecycle/ Planner/Executor/Steps/Handlers (mutex, commit-at-end, компенсация, reconcile, sync)
events/ ModuleLifecycleDispatcher (app-level шина межмодульных интеграций)
controllers/ backend/ModulesController (веб-интерфейс)
commands/ ModulesController + MenuController (консольные драйверы поверх того же фасада)
ModuleManager.php фасад — единый публичный API для драйверов
Контракты модуля вынесены в пакеты. Capability-интерфейсы (
DeclaresModule,Provides*) живут в пакетеbesnovatyj/yii2-cms-contracts(Besnovatyj\Contracts\module\*), а рантайм-базовый класс — вbesnovatyj/yii2-cms-kernel(Besnovatyj\Kernel\module\CmsModule). Менеджер и модули используют версии из пакетов; локального каталогаcontract/больше нет.
Подключение в приложение
1. Глобальный bootstrap — в app/common/config/main.php (app-level bootstrap), чтобы DI-проводка
и шина событий поднимались рано, до загрузки скомпилированных артефактов:
'bootstrap' => ['log', 'queue', \Besnovatyj\Modman\Bootstrap::class],
Bootstrap поднимает DI-контейнер менеджера и его канал лога modman/*. Это же решает chicken-and-egg:
менеджер обязан работать, чтобы скомпилировать конфиги, поэтому его проводка — глобальная, а не из
компилируемого артефакта.
2. Компилируемые артефакты — это и есть конфиг приложения. Менеджер пишет в канонические пути
(@config-dyn-gen/modulesConfigFile.php, componentsConfigFile.php, logChannelsConfigFile.php,
menu-*.php, …), которые приложение и так загружает. Никаких _new и аддитивного слияния — это
основной конфиг.
3. Холодный старт — автоматический. Bootstrap (шаг 1) сам регистрирует модуль Modman в
приложении (Application::setModule), поэтому менеджер доступен даже когда modulesConfigFile.php
пуст, устарел или ссылается на мёртвый старый id/namespace. Это разрывает chicken-and-egg: инструмент,
который компилирует артефакт модулей, не зависит от этого артефакта, чтобы запуститься, — руками
артефакт править не нужно (и нельзя, closed-loop compile-not-patch).
Регистрация идемпотентна (guard hasModule): как системный модуль (editable=false) Modman всё
равно попадёт в modulesConfigFile.php при следующей recompile и переживёт любую пересборку (см.
ARCHITECTURE §6); саморегистрация в bootstrap — постоянная страховка на холодный старт, а не костыль.
Использование
Веб: /Modman/backend/modules/index — список модулей/пакетов (фильтры по статусу/обновлениям,
сортировка, пагинация), «План» (dry-run), установка, обновление, удаление, «Сверка» (reconcile),
«Пересобрать конфиг», «Пересобрать меню». (sync — пока только в консоли, см. ниже.)
Консоль:
php yii Modman/modules/list
php yii Modman/modules/check <moduleId>
php yii Modman/modules/install <moduleId>
php yii Modman/modules/update <moduleId>
php yii Modman/modules/uninstall <moduleId>
php yii Modman/modules/reconcile
php yii Modman/modules/sync [--adoptAll] # пересобрать реестр из реальности (см. ниже)
php yii Modman/modules/recompile
php yii Modman/menu/info # диагностика локаций меню (вкл/выкл, файл, существование, число пунктов)
php yii Modman/menu/rebuild # перекомпилировать только артефакты меню
(Для консоли модуль также должен быть в modules console-приложения.)
sync — восстановление реестра из фактического состояния
Реестр modules-state.php — единственный источник истины, но если его файл затёрли/побили, штатного
способа восстановить его «из реальности» раньше не было (reconcile чинит только транзиентные записи,
уже присутствующие в реестре). sync закрывает эту точку отказа — без ручной правки файла и без
ручных контрольных сумм:
- набор модулей берётся из discovery (composer + скан
packages/besnovatyj); - применённые миграции — из БД-истории владения (
MigrationOwnershipRepository); manifestChecksum— пересчитывается детерминированно фабрикой манифестов.
«Установлен по факту» = уже installed в реестре, или за модулем числятся применённые миграции в
БД, или передан --adoptAll. Иначе модуль пропускается (используйте install). После пересборки
запускается recompile. Осиротевшие записи реестра (пакет исчез из каталога) не удаляются — только
сообщаются. --adoptAll (-a) — крайняя мера: усыновить как installed все обнаруженные
editable-модули для голого восстановления.
Маркер пакета CMS (extra.bescms)
Менеджер показывает только пакеты, явно помеченные как часть этой CMS, — чужие composer-зависимости
из vendor/ (после переезда в GitHub их будут сотни) в список не попадают. Маркер живёт в composer.json
в блоке extra (трогать type: yii2-extension нельзя — по нему Yii подключает свои bootstrap):
"extra": { "bescms": {"kind": "module"} }
kind: "module"— полноценный управляемый модуль. Должен также объявлятьextra.moduleClass/moduleIdи реализовывать контрактDeclaresModule(см. ниже). Попадает во вкладку «Модули».kind: "package"— пакет CMS без жизненного цикла (например, виджет). Виден во вкладке «Пакеты», но не устанавливается менеджером.
Пакет без маркера менеджер игнорирует. Модуль, помеченный kind: module, но с ошибкой конфигурации
(нет moduleClass, не реализует контракт, дубликат id), показывается строкой с причиной и погашенной
кнопкой установки; подробности уходят в лог-канал modman/*, а не во flash на всю страницу.
Контракт модуля
Модуль наследует тонкий рантайм-базовый класс Besnovatyj\Kernel\module\CmsModule (раскладка
controllerNamespace по контексту приложения, layout из активной темы, хук DI /config/container.php) и
реализует DeclaresModule плюс нужные Provides* (статические методы — discovery не инстанцирует класс):
use Besnovatyj\Kernel\module\CmsModule; use Besnovatyj\Contracts\module\DeclaresModule; use Besnovatyj\Contracts\module\ProvidesMigrations; final class Module extends CmsModule implements DeclaresModule, ProvidesMigrations { public static function moduleId(): string { return 'Shortcode'; } public static function moduleVersion(): string { return '1.0.0'; } public static function isEditable(): bool { return true; } public static function moduleConfig(): array { return ['id' => 'Shortcode', 'params' => [...]]; } public static function migrationPath(): string { return __DIR__ . '/migrations'; } public static function migrationNamespace(): ?string { return __NAMESPACE__ . '\\migrations'; } }
Соответствующий composer.json модуля объявляет и маркер, и класс/id:
"extra": { "bescms": {"kind": "module"}, "moduleClass": "Besnovatyj\\Shortcode\\Module", "moduleId": "Shortcode" }
Размещение контрактов. Контракты и базовый класс вынесены в отдельные пакеты (
besnovatyj/yii2-cms-contractsиbesnovatyj/yii2-cms-kernel), поэтому модули не зависят от менеджера.
Сам менеджер — обычный модуль.
modman/Moduleреализует тот жеDeclaresModuleсisEditable() === false: он виден в общем списке как «системный» (с версией, без кнопок установки/удаления), а не как исключение. Его проводка — глобальная (шаг 1), а в компиляцию он попадает как любой системный модуль.
Проверка синтаксиса (Docker)
docker compose exec php sh -c 'find /home/node/app/packages/besnovatyj/modman/src -name "*.php" -not -path "*/.git/*" -print0 | xargs -0 -n1 -P4 php -l'
Описание функционала и логики
Кнопка "Обновить" модуль
Это кнопка update-lifecycle модуля в modman — не git, не composer, не upstream-проверка. Она пересобирает интеграцию уже лежащего на диске кода модуля в приложение.
Путь: POST → actionUpdate → ModuleManager::update() → UpdateHandler::update().
Когда появляется: только если installed && hasUpdate, где
hasUpdate = модуль активен И (версия манифеста > версии в реестре ИЛИ checksum манифеста ≠ записанного в реестре).
То есть код на диске изменился (новый тег/новый вклад), а реестр modman ещё отражает старое состояние.
Что делает (под LifecycleLock + мьютексом):
- Пишет в реестр статус
Updating(write-ahead intent), шлёт событиеBeforeUpdate(на него могут реагировать другие модули). - Применяет только pending-миграции модуля — благодаря учёту владения миграциями, без
down→up/переустановки (в старом modman «обновление» = снести и поставить заново; здесь — настоящий инкрементальный апдейт). - Создаёт недостающие директории модуля (
@static/...). - Commit: обновляет запись в реестре — новая
version, новыйchecksum,updatedAt = now, список применённых миграций дополняется, статус →Installed. LifecycleExecutorв конце перекомпилирует конфигурацию (merge-plan/артефакты) из реестра.- При успехе — событие
AfterUpdateи отчёт «обновлён до vX» в модалке; при ошибке — rollback к прежнему установленному состоянию.
Чего она НЕ делает: не тянет новый код с GitHub и не запускает composer update — предполагается, что новый код уже
на диске (composer его уже поставил). Кнопка лишь синхронизирует под него БД-миграции, директории, реестр и
скомпилированный конфиг.
Кнопка-иконка «обновить, минуя кэш» в колонке Upstream — другое: она лишь заново запрашивает последний тег с GitHub, ничего в системе не меняя.
besnovatyj/yii2-cms-modman 适用场景与选型建议
besnovatyj/yii2-cms-modman 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 07 月 15 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「cms」 「modules」 「modman」 「yii2」 「module-manager」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 besnovatyj/yii2-cms-modman 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 besnovatyj/yii2-cms-modman 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 besnovatyj/yii2-cms-modman 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
This is Paymorrow module for OXID eShop.
A simple composer installer
GraphQL authentication for your headless Craft CMS applications.
Set Links with a specific language parameter
Supercharged text field validation.
Analysis module for finding problematical shop data.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-15