主题挂钩与模块挂钩


10

有时,当我尝试应用一个钩子时,只是意识到它应该在模块文件中。

有没有一种方法可以知道可以在主题的template.php文件中或模块中实现哪些钩子?


4
通常,当无法将挂钩替换为主题时,这是有充分理由的。主题应该仅用于与模块提供的内容和功能的显示有关的代码。添加/删除/更改功能或内容的代码通常应位于模块中。还考虑以下事实:如果更改主题,则会丢失在template.php中所做的任何自定义设置,因此,如果要进行更改(如果您曾经更改过主题则很可能希望保留),则肯定要加入模块中。
鲁比,2015年

Answers:


11

一般而言,只能通过主题实现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。
请记住,在主题的情况下,并非对所有启用的主题都进行了钩子实现检查,这与模块发生的情况相反。如“视图”模块中所述,仅检查当前使用的主题和基本主题。


hook_entity_view_alter()在主题中不起作用。
dxvargas

至少在D7中,仅当主题已经在同一请求中初始化时(即通过调用theme())才调用主题中的alter-hooks 。如果尚未初始化,则不会执行任何主题中的alter hook。
zwirbeltier

@zwirbeltier为用于呈现页面的主题调用主题挂钩。theme()不会更改用于页面的主题,但是会调用一个函数来呈现数据。它不会改变主题,例如,从Garland到Minelli。
kiamlaluno

@kiamlaluno:如果您看一下其中的代码,drupal_alter()就会发现它只在主题drupal_theme_initialize()被调用之前调用主题中的alter-hooks 。如果不是,则没有活动主题(尚未),因此也没有调用任何挂钩。至少在D7中,不能保证drupal_theme_initialize()在请求中首次调用何时。
zwirbeltier

@zwirbeltier呈现页面时,已经初始化了Drupal的主题集。如果模块为页面设置主题而不调用适当的功能,则初始化它是其责任。
kiamlaluno
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.