Тема
Исследование ядер CMS
Сравнение архитектур ядер восьми CMS для проектирования собственного ядра. Разбор механизмов расширяемости, стабильности и обновлений. Проверено по официальной документации и исходному коду. Выводы применены в Расширяемости и Центре обновлений.
Разобранные системы
Классические: 1С-Битрикс, WordPress, Drupal, TYPO3. Laravel-CMS: Statamic, Twill, Winter CMS, Botble CMS (+ Filament как admin-ядро, nwidart/laravel-modules).
Механизмы перехвата ядра — сравнение
| Система | Хуки/события | Изменить значение по цепочке | Замена без правки ядра | DI |
|---|---|---|---|---|
| 1С-Битрикс | EventManager, объект Event; AddEventHandler (на хит) / RegisterModuleDependences (в БД) | EventResult (блокирует/меняет операцию) | приоритет /local над /bitrix; наследование компонента | частичный |
| WordPress | actions + filters на классе WP_Hook | filters — уникальный примитив | child themes, drop-ins, mu-plugins | нет (глобалы) |
| Drupal | #[Hook]-атрибуты (11.1+) + PSR-14 events | alter-хуки | service decoration, theme suggestions | полный (Symfony) |
| TYPO3 | SC_OPTIONS (legacy) → PSR-14 events | нет отдельного примитива | TypoScript, decoration, XCLASS | полный (Symfony) |
Битрикс — уроки
/localнад/bitrix: система обновлений автоматически переписывает только/bitrix/modules/. Любая ручная правка внутри/bitrixмолча затирается при обновлении. Обработчик в/localфизически вне зоны обновления → переживает апдейт.init.php— свалка: признанный антипаттерн (сотни строк смешанной логики).- Слабые места: двойное легаси-ядро (
CDatabase+ D7 ORM); безопасность как ответственность разработчика → конкретные CVE (модулиvote,landing, CVSS 10/10); обновления безопасности требуют активной лицензии (vendor lock-in).
WordPress — уроки
- Filters — примитив, которого нет в Laravel: цепочка колбэков меняет и возвращает значение. Ближайший аналог в Laravel —
Illuminate\Pipeline. - Строгая граница
wp-content/vs core — делает безопасным форс-апдейт по чексуммам. - Слабые места: 91% уязвимостей WP — в плагинах (11 334 за 2025); плагин = часть ядра по правам (глобальный
$wpdbбез прослойки); implicit-хуки без типизации и реестра.
Drupal — уроки
- Service decoration (
decorates:в services.yml) — чистый паттерн обёртки сервиса с доступом к оригиналу и приоритетом; переживает минорные апдейты. - Class-based хуки (
#[Hook], 11.1+) с управлением порядком (OrderBefore/OrderAfter). - hook_update_N() — последовательные миграции схемы;
hook_post_update()— data-updates. - Слабые места: overengineering, крутая кривая обучения, boilerplate на простую фичу.
TYPO3 — уроки
- Иерархия предпочтений (официальная): события > hooks > decoration > XCLASS. Это и есть «лестница расширяемости».
- XCLASS — замена класса целиком, «last resort»: ломается при смене сигнатуры без предупреждения.
- Слабые места: четыре конфиг-синтаксиса (PHP+Fluid+TypoScript+YAML), высокий порог входа.
Statamic — что заимствуем (проверено по исходникам)
- Манифест
extra.statamicв composer.json (name/slug/editions/description), парсится классомManifest extends PackageManifest. Расширить полемminimum-core-version— его нет ни у Statamic, ни у Twill. AddonServiceProvider— декларативные свойства ($tags,$fieldtypes,$widgets)- автозагрузка по папкам (
src/Tags/,src/Fieldtypes/).
- автозагрузка по папкам (
UpdateScript(shouldUpdate()/update()) — версионные миграции аддона между релизами. Прямая заготовка под центр обновлений и миграции схем блоков (_v).- Типизированные Domain Events Saving/Saved на каждую сущность (
EntrySaving/Saved, 99 файлов событий) — паттерн для Filament-ресурсов сafterSave(). Брать (лучше Twill). - Лицензии: editions + единый license key на сайт + периодическая валидация.
Twill — что заимствуем и что нет
- Брать: CRUD-триада Controller/Repository/Model с базовыми классами, переопределяемыми через конфиг (
base_controller/base_repository/base_model) — механизм переопределения дефолтной реализации для всего парка сразу. Trait-hooks вModuleRepository(HandleSlugs,HandleMedias,HandleRevisions) — композиция поведения без глубокого наследования. - Не брать: событийная система слабая (строковый
fireCmsEvent()вместо типизированных Events); Capsule — internal-механизм организации кода, не редистрибутируемый unit с манифестом; нет marketplace-контракта.
Winter CMS — что заимствуем и что нет
- Брать: двухтабличная модель версий —
system_plugin_versions(текущая версия модуля) +system_plugin_history(журнал применённых скриптов для точного отката). Готовый паттерн центра обновлений: «откати сайт X на версию N модуля Y». Декларативныйversion.yaml(версия → миграции + changelog + флаг important). Каталог хуков расширения admin-форм (backend.form.extendFields,backend.list.extendColumns) — чек-лист точек расширения для Filament. - Не брать: транспорт обновлений (
winter:update— gateway-zip, несовместим с composer); Twig + Halcyon (чужеродно для Blade/Filament); собственный Backend UI.
Botble CMS — что заимствуем и что нет
- Брать: lifecycle плагина
activate()/deactivate()/remove()(remove()чистит данные плагина);plugin.jsonсminimum_core_version; fluentLoadAndPublishDataTrait(DX базового провайдера); декларативныйconfig/permissions.php(но материализовать в spatie/laravel-permission, не JSON-флаги); license-API контракт как прообраз (check/latest/download, «1 лицензия = 1 домен»). - Не брать: транспорт (overwrite директорий
platform/coreповерх ФС — хрупко, не откатывается); WP-styledo_action/apply_filters(singleton-реестр сkrsort/ksort— анти-Laravel магия); Envato/CodeCanyon-модель; ядро закрытое (нельзяcomposer require).
Итоговый принцип
Ключевая идея всех систем: строгая граница «ядро / пользовательский код» — фундамент безопасных обновлений. В Laravel она уже существует бесплатно (vendor/ vs app/). Стратегия — не копировать чужие ядра, а достроить поверх Laravel недостающие примитивы:
| Достроить | Источник идеи |
|---|---|
| Фильтры (значение по цепочке) | WordPress |
| Порядок слушателей (before/after) | Drupal 11 / TYPO3 |
| Открытый BlockRegistry | своё (переделка universal) |
| Каскад тем + suggestions | WordPress + Drupal |
| Decoration с приоритетом | Drupal |
Манифест minimum-core-version | Statamic + своё |
UpdateScript версионные миграции | Statamic |
| Двухтабличная модель версий | Winter |
| Lifecycle activate/deactivate/remove | Botble |
Версии схем блоков (_v) | WordPress Gutenberg |
Реестр точек расширения cms:hooks | своё (нет ни у кого) |
Из антипаттернов явно избегать: init.php-свалки (Битрикс), глобального состояния и «плагин = ядро по правам» (WP), четырёх конфиг-синтаксисов (TYPO3), boilerplate на простую фичу (Drupal), собственного транспорта обновлений (Winter/Botble).