Хуки в Drupal 10 и 11: типичные ошибки и как их ловить
Хук в Drupal может не сработать из-за одной буквы в имени, кеша или неверной сигнатуры. Разбираем ошибки в preprocess, form alter и entity-хуках, а также критерии выбора подхода.

В Drupal 10 и 11 хук часто выглядит исправным, но не выполняется: функция названа не по machine name модуля, после изменения не сброшен кеш, а аргументы не совпадают с контрактом конкретного расширения. Цена ошибки — от незаметного отсутствия CSS-класса до сохранения неправильных данных в базе. Ниже — практический разбор для тех, кто уже пишет модули и хочет быстро находить такие сбои.
Сначала определите точку расширения
Хук — это соглашение между ядром Drupal и модулем. Ядро вызывает функцию с ожидаемым именем и набором аргументов, а модуль меняет данные или запускает побочный эффект. Поэтому ошибка может быть не в теле функции, а в самом выборе точки входа.
| Задача | Подход | Цена и риск |
|---|---|---|
| Добавить классы или переменные в шаблон | hook_preprocess_HOOK() | Работает на этапе подготовки рендера. Не меняет исходную сущность и не подходит для бизнес-логики. |
| Изменить определение формы | hook_form_alter() или hook_form_FORM_ID_alter() | Даёт точный контроль над формой, но требует правильного form ID и очистки кеша. |
| Реагировать на сохранение сущности | Entity-хуки, например hook_entity_insert() | Подходит для побочных действий после создания. Ошибка в обработчике может замедлить или сорвать сохранение. |
| Изменить данные, которые передают другим обработчикам | Хуки с суффиксом _alter | Обычно меняют массив по ссылке. Неверная структура приводит к ошибке позже, уже вне вашего кода. |
Если хук не сработал, сначала проверяйте его имя, файл и кеш. Отладка тела функции до этой проверки часто тратит время впустую.
Сноска. Обнаружение реализации — механизм, с помощью которого Drupal находит функции модулей и запоминает результат в кеше. Поэтому добавленная или переименованная реализация не всегда видна сразу.
Ошибка 1. Неверное имя функции
Имя строится из machine name модуля и имени хука. Если модуль называется catalog_tools, реализация preprocess для узла должна называться catalog_tools_preprocess_node(). Имя каталога, человекочитаемое название модуля и имя функции — не одно и то же.
<?php
/**
* Подготавливает переменные для шаблона узла.
*/
function catalog_tools_preprocess_node(array &$variables): void {
$variables['attributes']['class'][] = 'node--catalog-tools';
}
Файл должен лежать в модуле, обычно это catalog_tools.module. Функция не должна находиться в теме, если вы рассчитываете на реализацию хука модуля. После переименования модуля проверьте все префиксы: Drupal не сопоставляет функцию с модулем по содержимому файла.
Ошибка 2. Хук добавили, но не сбросили кеш
Drupal кеширует сведения о найденных реализациях. Изменение тела функции обычно видно сразу, но добавление нового хука, переименование функции или изменение некоторых определений требует перестроения кешей.
Для окружения с Drush используйте команду, принятую в вашей версии Drush:
drush cache:rebuild
Проверка простая: добавьте временную запись в лог, а затем откройте страницу, где должен вызываться хук. Для рабочего сайта не оставляйте отладочный вывод и не выводите значения через print или var_dump: это может повредить HTML или ответ AJAX.
Ошибка 3. Перепутали общий и точечный alter
Общий hook_form_alter() вызывается для форм, а точечный вариант содержит form ID. Например, для модуля catalog_tools точечная реализация может выглядеть так:
<?php
use Drupal\Core\Form\FormStateInterface;
/**
* Добавляет подсказку только в форму поиска по сайту.
*/
function catalog_tools_form_search_block_form_alter(
array &$form,
FormStateInterface $form_state,
$form_id
): void {
$form['keys']['#description'] = 'Введите минимум три символа.';
}
Здесь критичны сразу три детали: machine name модуля, точный form ID и изменение массива формы по ссылке. Если вы напишете catalog_tools_form_search_form_alter, но реальный ID — search_block_form, функция не вызовется.
Узнать form ID можно через временный лог в общем catalog_tools_form_alter() или через инструменты отладки формы. Не копируйте название класса формы вслепую: class name и form ID могут отличаться.
Ошибка 4. Сигнатура не соответствует хуку
Drupal передаёт аргументы в порядке, который определён конкретным хуком. Нельзя взять сигнатуру hook_form_alter() и применить её к entity-хуку. Нельзя убирать обязательный аргумент только потому, что он не нужен внутри функции.
При проверке реализации сопоставьте четыре вещи:
- название хука и его точную разновидность;
- порядок аргументов;
- передачу массива по ссылке, если это предусмотрено контрактом;
- тип аргумента, если вы добавляете типизацию.
Особенно осторожно используйте строгую типизацию в старом коде. Если реальная сигнатура хука допускает несколько вариантов или менялась между ветками Drupal, жёсткий тип может превратить рабочий обработчик в фатальную ошибку. Для конкретного хука сверяйтесь с API-документацией той ветки Drupal, на которой работает сайт.
Ошибка 5. От хука ждут не того этапа
preprocess_node работает при подготовке вывода узла, а не при его сохранении. Изменение переменной в preprocess не запишет значение в поле сущности. И наоборот, entity-хук не является способом добавить CSS-класс в конкретный шаблон.
Типичный промах выглядит так: разработчик меняет данные внутри hook_entity_insert(), затем вызывает повторное сохранение той же сущности и получает цикл или неожиданные побочные действия. Если требуется изменить данные до записи, выбирайте обработчик предварительного сохранения и проверяйте, что изменение не запускает повторный вызов вашей логики.
Сохранение, вывод и изменение формы — разные этапы. Связывать их в одном хуке удобно только до первого нестандартного сценария: импорта, AJAX-формы, пакетного обновления или повторного сохранения.
Ошибка 6. Alter меняет массив, но ломает его структуру
Хуки с суффиксом _alter дают возможность изменить массив, который затем обработает ядро или другой модуль. Ошибка может проявиться не в строке изменения, а позже — например, когда Drupal ожидает render array, а получает обычную строку.
Перед изменением найдите документацию именно для этого alter-хука и посмотрите, какие ключи разрешены. Не заменяйте весь массив ради одной настройки, если достаточно изменить конкретный ключ. Так вы не удалите значения, добавленные ядром или другим модулем.
Что выбрать в рабочем проекте
Если меняется только отображение
Начинайте с preprocess-хука или настройки темы. Это самый дешёвый по последствиям вариант: данные сущности остаются прежними, а изменение ограничено выводом. Для бизнес-правил такой подход не используйте — другой контроллер или экспорт не увидит вашу логику.
Если меняется форма
Выбирайте точечный form alter, когда известен form ID. Общий form alter оставляйте для логики, которая действительно должна применяться к нескольким формам. В обоих случаях проверяйте, что поле существует: разные режимы формы и права пользователя могут давать разную структуру.
Если важен жизненный цикл сущности
Используйте entity-хук, когда действие связано с созданием, изменением или удалением сущности. Отдельно проверьте импорт и массовые операции: обработчик, который без проблем работает для одного сохранения, может многократно увеличивать время пакетной загрузки.
Что ломается чаще всего
- Функция не вызывается. Проверьте machine name, имя файла, включён ли модуль и сброшен ли кеш.
- Изменение не видно в браузере. Проверьте, действительно ли страница использует нужный шаблон и не отдаётся ли старый результат из кеша рендера.
- Появился фатальный TypeError. Сверьте количество, порядок и типы аргументов с документацией хука.
- Форма не меняется. Выведите фактический form ID и убедитесь, что поле находится по указанному пути.
- После изменения пропали другие элементы. Вы, вероятно, заменили массив целиком вместо изменения одного ключа.
Как проверять хуки до выката
Минимальный тест должен проверять не только вызов функции, но и результат на реальном сценарии. Для preprocess откройте страницу с нужным типом сущности. Для form alter проверьте анонимного пользователя, администратора и AJAX-вариант, если он есть. Для entity-хука проверьте создание, редактирование, импорт и повторное сохранение.
В логах оставляйте контекст: идентификатор сущности, form ID или имя маршрута. Не записывайте туда персональные данные и содержимое пользовательских полей без необходимости. После проверки удалите временный лог и перестройте кеши перед повторным тестом.
Что делать дальше
Возьмите один неработающий хук и составьте короткую цепочку проверки: machine name, файл, точная сигнатура, условие вызова, кеш и ожидаемый результат. Затем добавьте автоматический тест или хотя бы повторяемый сценарий в тестовом окружении. Для продакшена отдельно наблюдайте время сохранения сущностей и ошибки PHP: именно там безобидный на вид entity-хук чаще всего превращается в узкое место.
Репетитор 1—11 класс и ВУЗ: Математика и физика методом наведения на мысль, помощь с ДЗ.
Спросить за 8 ₽Источники: Drupal.org: Understanding hooks, Drupal API: Hooks, Drupal 11
Частые вопросы
Почему Drupal не видит новый хук после добавления функции?
Как узнать правильный form ID для hook_form_FORM_ID_alter?
Что будет, если я не успел сбросить кеш после изменения хука?
Можно ли использовать preprocess-хук для изменения данных узла?
Почему хук работает на одной странице, но не работает в AJAX-форме?
Что делать, если код написан для другой версии Drupal?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.