我正在开发一个模块,但是我要添加的钩子没有从Drupal调用。它发生在多个钩子上。
我阅读了有关挂钩的文档,但找不到任何可以解释为什么发生这种情况的内容。我确认我使用了正确的参数,并返回了正确的值。
我究竟做错了什么?我有什么想念的吗?
我正在开发一个模块,但是我要添加的钩子没有从Drupal调用。它发生在多个钩子上。
我阅读了有关挂钩的文档,但找不到任何可以解释为什么发生这种情况的内容。我确认我使用了正确的参数,并返回了正确的值。
我究竟做错了什么?我有什么想念的吗?
Answers:
在开发模块时,应牢记以下注意事项。
从模块完成钩子的实现是一个函数,该函数的名称以模块短名称(也称为机器名)为前缀。从挂钩名称中脱下挂钩部分,然后将其替换为模块机器名称。例如,hook_menu()example.module 的done 实现是example_menu()。如果模块为example_menu.module,而函数为example_menu(),则不视为hook_menu()example_menu.module 的实现。
例如,这还意味着hook_form_alter()example_form.module 中的实现不是example_form_alter(),而是example_form_form_alter()。再举一个例子,不是hook_form_FORM_ID_alter()为了更改user_register_form()从example.module 返回的表单而完成的实现example_form_user_register_alter(),而是example_form_user_register_form_alter()。(表单ID为user_register_form。)
一般而言,在模块机器名称中使用大写字母不会产生问题:PHP不会在myModule_get_value()和mymodule_get_value()和之间产生区别,而是$value = myModule_get_value()会调用myModule_get_value()或mymodule_get_value()。
但是,在某些情况下,在模块机器名称中使用大写字母会引起问题:在为模块定义更新挂钩时。drupal_get_schema_versions(),该函数返回可用更新的列表,其中包含以下代码。
// Prepare regular expression to match all possible defined hook_update_N().
$regexp = '/^(?P<module>.+)_update_(?P<version>\d+)$/';
$functions = get_defined_functions();
// Narrow this down to functions ending with an integer, since all
// hook_update_N() functions end this way, and there are other
// possible functions which match '_update_'. We use preg_grep() here
// instead of foreaching through all defined functions, since the loop
// through all PHP functions can take significant page execution time
// and this function is called on every administrative page via
// system_requirements().
foreach (preg_grep('/_\d+$/', $functions['user']) as $function) {
  // If this function is a module update function, add it to the list of
  // module updates.
  if (preg_match($regexp, $function, $matches)) {
    $updates[$matches['module']][] = $matches['version'];
  }
}执行的最后一行drupal_get_schema_versions()是下一行。
return empty($updates[$module]) ? FALSE : $updates[$module];如果模块名称为myModule.module,drupal_get_schema_versions('myModule')则仅返回名称以myModule_update开头,以数字结尾的函数;之类的函数mymodule_update_7120()不会包含在内,因为from drupal_get_schema_versions()中使用的正则表达式区分大小写。这仍然适用于Drupal 8,因为正则表达式仍与Drupal 7中使用的正则表达式相同。
一些挂钩在特定时刻被调用。例如,在启用/禁用模块后或清除路由器信息的缓存后,从Drupal 7中调用hook_menu(),和hook_menu_alter()。hook_init()不为缓存的页面调用。
一旦挂钩因特定事件发生而被调用,它们将不会再次调用,直到类似事件不再发生为止。在两个连续的页面请求中未调用它们。
Drupal缓存从模块实现的挂钩列表。如果您正在编辑已启用模块的代码以添加新的挂钩,则首先需要禁用并重新启用该模块,否则Drupal不会注意到有新的挂钩。
确保return在重构过程中语句不会潜入您的钩子函数之一。它不仅可能破坏它出现的钩子,而且还可能导致连锁反应也破坏其他钩子,从而使问题很难定位。