Проблема с кодом вне функций в Drupal 6 и 7
Столкнулся с интересной проблемой, которую удалось повторить и в Drupal 6, и в Drupal 7. В модуле вне тела функции была объявлена константа:
define('TEST_CONST', drupal_get_path('module', 'test_module'));
(тут дело даже не в самой константе, а в использовании апишной функции drupal_get_path() вне тела функции).
Этот модуль долгое время корректно работал, до тех пор пока в нем не был объявлен hook_exit(). После этого события Друпал начал отдавать ошибку "PHP Fatal error: Call to undefined function drupal_get_path() in..."
, где вместо drupal_get_path()
можно поставить почти любую функцию из Drupal API, которая была использована в коде, расположенном вне тела функций.
Поиск и исправление причин ошибки осложнился тем, что она стала проявляться не сразу после добавления hook_exit()
, а спустя некоторое время.
Суть ошибки оказалась в следующем:
- Друпал в таблице
system
, модулям которые реализуютhook_exit()
, проставляет значение1
в колонкеbootstrap
, по умолчанию этот параметр равен нулю. - В свою очередь модули отмеченные таким образом начинают загружаться Друпалом раньше остальных (на этапе
DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE
в случае Drupal 6) когда API, в частности файл common.inc, содержащий функциюdrupal_get_path()
, еще не загружен полностью. - Загрузка модуля подразумевает include файла модуля и, что логично, исполнение кода, находящегося вне тела функций.
Таким образом, после добавления hook_exit()
модуль стал загружаться до полной загрузки API и функция drupal_get_path()
на этом этапе действительно еще не была определена. Решилась проблема переносом проблемного кода в hook_init()
.
Возникла ошибка не сразу от того, что обновление поля bootstrap
в таблице system
делается не сразу, а при обновлении кеша списка модулей (вызов функции module_rebuild_cache()
в Drupal 6). Этот кеш очищается, например, при нажатии кнопки “Сохранить” на странице списка модулей или при срабатывании модуля Update status.