我正在开发一个模块,但是我要添加的钩子没有从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
在重构过程中语句不会潜入您的钩子函数之一。它不仅可能破坏它出现的钩子,而且还可能导致连锁反应也破坏其他钩子,从而使问题很难定位。