Drupal: свои модули и плагины вместо правок ядра
Опубликовано: 02.09.2026
Drupal устроен так, что почти любую задачу можно решить снаружи ядра. Это не декларация из документации, а следствие архитектуры: платформа изначально проектировалась как набор точек расширения, а не как готовый продукт, который дорабатывают напильником.
Почему правка ядра — тупик
Аргумент «мы поправим одну строчку, это быстрее» звучит убедительно ровно до первого обновления. Дальше начинается цепочка последствий:
- Обновления перестают быть рутиной. Каждое обновление ядра требует ручного сведения изменений, а значит откладывается — включая критические патчи безопасности.
- Правку невозможно передать. Через год никто не помнит, зачем изменена строка в
NodeViewBuilder, и трогать её боятся. - Composer перезатирает изменения. Штатный процесс развёртывания просто выкачивает ядро заново, и правка исчезает в самый неудобный момент.
Отдельно стоит сказать про патчи через composer-patches. Это уже лучше, чем правка руками: патч лежит в репозитории и применяется воспроизводимо. Но патч ломается при обновлении, и его всё равно нужно сопровождать. Разумно применять его только к чужим contrib-модулям и только когда исправление уже отправлено в upstream.
Точки расширения, которые закрывают почти всё
Прежде чем думать о патче, стоит пройтись по штатным механизмам — их больше, чем кажется:
- Хуки. Старый, но живой механизм.
hook_form_alter(),hook_entity_presave(),hook_preprocess_HOOK()закрывают огромный пласт задач по изменению форм, данных и вывода. - Подписка на события Symfony. Там, где нужен контроль над HTTP-циклом, маршрутизацией или реакцией на системные события, EventSubscriber удобнее хука: его легко тестировать и он явно объявлен в сервисах.
- Плагины. Механизм для случаев, когда нужен новый экземпляр существующего типа сущности кода: блок, форматтер поля, виджет, условие, действие.
- Сервисы и декораторы. Если нужно изменить поведение существующего сервиса, его можно декорировать через
ServiceProviderили тегdecorates, не трогая исходный класс.
Плагины: когда именно они
Плагин — это ответ на вопрос «нужен ещё один такой же, но другой». Новый тип блока, новый форматтер для поля, новое условие видимости, новый источник миграции. Система плагинов даёт обнаружение по аннотациям или атрибутам, единый менеджер и предсказуемое место в структуре модуля.
Практическая польза здесь в том, что плагин самодостаточен. Он лежит в src/Plugin/Block/MyBlock.php, объявляет себя сам и не требует регистрации в десяти местах. Когда через год понадобится убрать функциональность, достаточно удалить один файл.
Ошибка, которую делают часто: писать плагином то, что должно быть сервисом. Если код не создаёт новый экземпляр известного платформе типа, а просто выполняет бизнес-логику, ему место в сервисе.
Сущности и поля вместо своих таблиц
Соблазн создать свою таблицу и работать с ней напрямую через \Drupal::database() велик, особенно у разработчиков, пришедших из других платформ. Иногда это оправдано — например, для лога на десятки миллионов строк, которому не нужны ни права доступа, ни ревизии, ни переводы.
Во всех остальных случаях лучше объявить контентную сущность. Она бесплатно получает систему прав, поддержку полей, ревизии, мультиязычность, интеграцию с Views и REST. Своя таблица всего этого не имеет, и через полгода функциональность приходится дописывать вручную — обычно хуже, чем в ядре.
Конфигурационные сущности решают смежную задачу: они описывают настройки, которые должны переноситься между окружениями через Configuration Management, а не редактироваться в базе продакшена.
Конфигурация в коде, а не в базе
Configuration Management — то, что отличает управляемый Drupal-проект от неуправляемого. Настройки типов материалов, полей, представлений и прав экспортируются в YAML, попадают в репозиторий и применяются на других окружениях командой drush config:import.
Практический признак здоровья проекта простой: после drush config:export на продакшене не должно появляться изменений. Если появляются — значит, кто-то правит настройки в обход процесса, и следующий деплой их снесёт.
Если вмешаться в ядро всё-таки нужно
Такие случаи существуют, но их меньше, чем кажется. Прежде чем патчить, стоит пройти короткий чек-лист:
- Есть ли issue на drupal.org с этой проблемой? Часто патч уже написан и обсуждается.
- Нельзя ли декорировать сервис вместо правки класса?
- Нельзя ли перехватить результат хуком или подписчиком уже после того, как ядро отработало?
Если ответ на все три вопроса отрицательный, патч оформляется через Composer, снабжается ссылкой на issue и комментарием «зачем», и попадает в список того, что проверяется при каждом обновлении. Это не идеально, но такой патч хотя бы виден.
Что это даёт на дистанции
Проект, где все доработки лежат в собственных модулях, обновляется рутинно: composer update, прогон тестов, drush updb, проверка. Проект с правками ядра обновляется как отдельная задача с оценкой в днях. Разница накапливается годами и в какой-то момент превращается в решение «проще переписать».