我很难理解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),
),
);
你能提供一个如何运作的例子吗?
答案 0 :(得分: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中的文档),因为它:
在Drupal 8中,theme()是一个私有函数_theme()。有关详细信息,请参阅www.drupal.org/node/2173655。
当您将上述两个元素与上面给出的示例中的poll_results
元素进行比较时,您可以解决正在发生的事情......因为PHP不是强类型语言,Drupal通过以下方式提供“命名参数”传递给theme
函数的键控数组,或渲染数组中的散列键。
就“渲染元素”而言,这基本上告诉主题系统将使用渲染数组调用此主题函数,其中一个命名参数(在本例中为{{1} })。代码看起来像这样:
form
这会将$build = array(
'#theme' => 'poll_choices',
'#form' => $form
);
变量中的任何内容传递给主题函数,因为它是唯一的参数。
关于$form
密钥:
template
定义了一个名为'poll_vote' => array(
'template' => 'poll-vote',
'render element' => 'form',
)
的主题,该主题使用名为“poll-vote.tpl.php”的模板文件(因此为poll_vote
键)(按照惯例)。通过使用实现它的模块的路径(例如modules / poll / poll-vote.tpl.php)可以找到该模板文件的路径,因此可以将模板文件放在主模块文件夹的子文件夹中
有两种方法可以实际返回主题函数的输出,方法是实现物理函数名称(在本例中为template
)或使用模板文件。如果theme_poll_vote
键为空,Drupal将假设您已实现了物理功能并将尝试调用它。
如果您要为主题输出相当多的HTML,或者您根本不喜欢在PHP中的字符串中编写HTML(我个人不这样做),那么模板文件是首选。但在任何一种情况下,调用主题时传递的变量(使用template
或如上所述的渲染数组)本身都会传递给模板文件或主题函数。所以:
theme()
如果您使用模板文件代替同一方法,则变量将以function theme_poll_results(&$vars) {
$raw_title = $vars['raw_title'];
$results = $vars['results'];
// etc...
}
,$raw_title
等方式提供,因为Drupal在$results
上运行extract
在解析模板文件之前。
我确信我在这里错过了很多,但如果你有任何更具体的问题请求,我会尽力帮忙。
答案 1 :(得分:0)
还有另一种方式:(可以在Bartik主题中找到)
这里的场景是我们已经创建了自己的模块,并希望覆盖默认输出,让我们说一个标题为'zzz'的节点。
我们不知道也不关心如何生成默认输出。我们所需要的只是告诉Drupal使用我们自己的自定义模板文件(node-custom-name.tpl.php)来呈现该特定节点。
这些是步骤:
告诉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;
}
告诉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'文件位于声明的路径中,否则它将继续根据建议命名约定进行搜索后备模板。