Answers:
一般而言,只能通过主题实现alter钩子,这意味着像hook_form_alter()
和的钩子hook_menu_alter()
,或者简而言之,是drupal_alter()
在Drupal 7和更低版本(ModuleHandler()::alter()
或ThemeManager::alter()
Drupal 8)中调用的所有那些钩子。
其他钩子module_invoke_all()
(ModuleHandler::invokeAll()
在Drupal 8中由()调用)不会仅针对主题而被调用,原因是代码不会检查当前启用的主题是否定义了任何钩子。
foreach (module_implements($hook) as $module) {
$function = $module . '_' . $hook;
if (function_exists($function)) {
$result = call_user_func_array($function, $args);
if (isset($result) && is_array($result)) {
$return = array_merge_recursive($return, $result);
}
elseif (isset($result)) {
$return[] = $result;
}
}
}
在Drupal 8中,ModuleHandler
类调用由模块实现的钩子,而ThemeManager
类调用由主题实现的钩子,只有第一个类实现invoke()
和invokeAll()
。这意味着在Drupal 8中,Drupal核心不会调用主题挂钩。
这对Drupal核心挂钩有效,并且大多数对第三方模块使用的所有挂钩都有效。然后由模块来验证挂钩是否也由主题实现,并调用它。这就是“视图”模块的作用。
// Let modules modify the view just prior to rendering it.
foreach (module_implements('views_pre_render') as $module) {
$function = $module . '_views_pre_render';
$function($this);
}
// Let the themes play too, because pre render is a very themey thing.
foreach ($GLOBALS['base_theme_info'] as $base) {
$function = $base->name . '_views_pre_render';
if (function_exists($function)) {
$function($this);
}
}
$function = $GLOBALS['theme'] . '_views_pre_render';
if (function_exists($function)) {
$function($this);
}
对于第三方模块使用的挂钩,您需要检查用于调用它们的代码。很有可能只为主题调用alter hook,但在某些情况下,主题也可以实现其他hook。
请记住,在主题的情况下,并非对所有启用的主题都进行了钩子实现检查,这与模块发生的情况相反。如“视图”模块中所述,仅检查当前使用的主题和基本主题。
theme()
)才调用主题中的alter-hooks 。如果尚未初始化,则不会执行任何主题中的alter hook。
theme()
不会更改用于页面的主题,但是会调用一个函数来呈现数据。它不会改变主题,例如,从Garland到Minelli。
drupal_alter()
就会发现它只在主题drupal_theme_initialize()
被调用之前调用主题中的alter-hooks 。如果不是,则没有活动主题(尚未),因此也没有调用任何挂钩。至少在D7中,不能保证drupal_theme_initialize()
在请求中首次调用何时。