8

我很难理解hook_theme()的作用。

我的理解是,它与使覆盖模板成为可能有关。

我在看:

  $theme_hooks = array(
    'poll_vote' => array(
      'template' => 'poll-vote',
      'render element' => 'form',
    ),
    'poll_choices' => array(
      'render element' => 'form',
    ),
    'poll_results' => array(
      'template' => 'poll-results',
      'variables' => array('raw_title' => NULL, 'results' => NULL, 'votes' => NULL, 'raw_links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL),
    ),
    'poll_bar' => array(
      'template' => 'poll-bar',
      'variables' => array('title' => NULL, 'votes' => NULL, 'total_votes' => NULL, 'vote' => NULL, 'block' => NULL),
    ),
  );

你能举例说明它是如何工作的吗?

4

3 回答 3

22

它为模块提供了一个定义主题的地方,然后可以被任何其他模块/主题覆盖。它还将为任何模块提供使用钩子的机会,例如mymodule_preprocess_theme_name更改传递给最终主题函数或模板文件的变量。

初始化主题函数基本上有两种方法:

theme('poll_results', array('raw_title' => 'title', 'results' => $results, etc...));

$build = array(
  '#theme' => 'poll_results',
  '#raw_title' => 'title',
  '#results' => $results,
  etc...
); // Note the '#' at the beginning of the argument name, this tells Drupal's `render` function that this is an argument, not a child element that needs to be rendered.

$content = render($build); // Exact equivalent of calling the previous example now that you have a render array.

请记住,您应该避免直接调用 theme()(根据 theme.inc 中的文档),因为它:

  • 规避缓存。
  • 规避 hook_element_info() 中定义的类型的默认值,包括附加资产
  • 绕过 pre_render 和 post_render 阶段。
  • 绕过 JavaScript 状态信息。

在 Drupal 8 中,theme() 是一个私有函数,_theme()。有关更多详细信息,请参阅www.drupal.org/node/2173655

当您将这两个与poll_results上面给出的示例中的元素进行比较时,您可能会弄清楚发生了什么......因为 PHP 不是一种强类型语言 Drupal 通过传递给theme函数的键控数组提供“命名参数” ,或作为渲染数组中的散列键。

就“渲染元素”而言,这基本上告诉主题系统将使用渲染数组调用此主题函数,并带有一个命名参数(在本例中form)。代码看起来像这样:

$build = array(
  '#theme' => 'poll_choices',
  '#form' => $form
);

这会将$form变量中的任何内容作为唯一参数传递给主题函数。

关于template关键:

'poll_vote' => array(
  'template' => 'poll-vote',
  'render element' => 'form',
)

定义了一个名为的主题poll_vote,它使用一个名为“poll-vote.tpl.php”的模板文件(因此是template密钥)(这是按照惯例)。该模板文件的路径将通过使用实现它的模块的路径来找到(例如 modules/poll/poll-vote.tpl.php),因此可以将模板文件放在主模块文件夹的子文件夹中.

有两种方法可以实际返回主题函数的输出,通过实现物理函数名称(在本例中为theme_poll_vote)或使用模板文件。如果template键为空 Drupal 将假定您已经实现了一个物理函数并尝试调用它。

如果您有相当多的 HTML 来为主题输出,或者您只是不喜欢在 PHP 中以字符串形式编写 HTML(我个人不喜欢),则模板文件更可取。theme()但是,在任何一种情况下,调用主题时传递的变量(如上所述使用或渲染数组)本身都会传递给模板文件或主题函数。所以:

function theme_poll_results(&$vars) {
  $raw_title = $vars['raw_title'];
  $results = $vars['results'];
  // etc...
}

如果您使用模板文件而不是相同的方法,则变量将作为 , 等可用$raw_title$results因为 Drupalextract$vars解析模板文件之前运行。

我敢肯定我在这里错过了很多东西,但是如果您有任何更具体的问题,请尽管提出,我会尽力提供帮助。

于 2011-10-12T16:52:10.720 回答
3

Drupal 6

我整天都被这个问题困扰,现在已经成功实施,所以在这里分享我的发现,可能有助于理解hook_theme

涉及3个步骤:

  1. hook_theme

    function YOURMODULENAME_theme() {
      return array(
        'xxx_xxx' => array(
        'template' => 'xxx-xxx', // define xxx-xxx.tpl.php inside module
        'arguments' => array('xxx' => null), //define $xxx so it will available in your xxx-xxx.tpl.php
        ),
      );
    }
    
  2. echo/return.tpl或任何的主题.module

    $output = theme('xxx_xxx', $xxx);
    
  3. 现在变量在你身上神奇地可用xxx-xxx.tpl.php

    <?php echo $xxx ?>
    

注意:您可以将 $xxx 作为数组、对象或任何东西传递 :)

于 2012-03-13T11:37:24.070 回答
0

还有另一种方法:(可以在 Bartik 主题中找到)

这里的场景是我们已经创建了自己的模块,并且想要覆盖默认输出,假设只有一个标题为“zzz”的节点。
我们不知道也不真正关心默认输出是如何生成的。我们只需要告诉 Drupal 使用我们自己的自定义模板文件 (node--custom--name.tpl.php) 来渲染那个特定的节点。

这些是步骤:

  1. 告诉 Drupal 我们的模板文件在哪里。(请记住,此功能只会在清除 Drupal 的缓存后才生效一次):

    // Implements hook_theme()
    function mymodulename_theme() { 
      $theme = array();
      $theme['node__custom__name'] = array(
        'render element' => 'node',
        'template' => 'path_from_mymodule_root/node__custom__name',
        );
      return $theme;
    }
    
  2. 告诉 Drupal 何时何地使用它

    //Implements hook_preprocess_node()
    function mymodulename_preprocess_node($vars) {
        if($vars['node']->title == 'zzzz') {
            $vars['theme_hook_suggestions'][] = 'node__custom__name';
            ... your other code ...
         }
     }
    

    现在 Drupal 将仅针对特定情况使用我们的模板文件,前提是 'node--custom--name.tpl.php' 文件位于声明的路径中,否则它将根据建议命名约定继续搜索备用模板.

于 2013-11-19T09:56:10.323 回答