What Is a Theme Hook?
In Drupal, theme hooks refer to template files and functions that have been specifically registered via hook_theme(). This may sound scary or over-technical to non-PHP developers, but honestly it’s not. You’ve already learned about template files and theme functions, so technically you already have a pretty good grasp on theme hooks.
Whether a template file or function is implemented in core is decided on a case-by-case basis, and the criteria for making this decision is usually a balance between how likely it is to be reused by other modules, how often it is expected to change, and whether or not it makes sense for performance reasons. Template files are slightly slower than theme functions so they are not always desirable. Smaller bits of markup for things like form input elements are more efficiently implemented as theme functions, whereas larger chunks like nodes and blocks are better as a template file.
• Both theme functions and template files exist as a way for Drupal and its modules to create output consisting of markup and variables in a way that you, the themer, can override and make it your own. They are both entirely YOUR domain, and you get the last word as to how they should look.
• Both share the same exact theme hook. For example, a template file called node.tpl.php and a function called theme_node() share the same node theme hook. The difference is in the implementation, as both cannot be used at the same time.
• Both can take advantage of preprocess functions, which allow you to intercept and alter variables before rendering. Using the node hook as an example, this would look like template_preprocess_node(); in your theme it would be yourtheme_preprocess_node().
Theme Hook Suggestions
The default implementation of template files and theme functions offer a very generic set of markup that is sufficient, but not ideal in all cases. When doing a standard override, such as copying block.tpl.php into a theme, the changes made will apply site-wide whenever a block is rendered. At times this the desired result, but you’ll often want to make changes to a specific block, a set of blocks provided by a specific module, or even a group of blocks in a specific region. Theme hook suggestions allow you to implement targeted overrides in your theme for both template files and theme functions with naming patterns. The options and naming patterns vary depending on what type of object you are working with. During the preprocess stage, before each template is rendered, a variable called $theme_hook_suggestions is created and populated with alternative hook suggestions.
Suggestions and Template Files
All of the common template files listed in Table 15–1 can be overridden to allow for more targeted customization by simply changing the name of the template file. When working with blocks, for example, Drupal suggests the options in Listing 15–15 during template_preprocess_block().
Listing 15–15. Excerpt from template_preprocess_block() where template suggestions for block template files are defined
<?php
//在template.php文件中,重载block.tpl.php
function mytheme_preprocess_block($variables) {
//do somethings
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->region;
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module;
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' .
$variables['block']->delta;
}
?>
Table 15–4. Template Suggestions for Blocks
Suggestion | Template File Equivalent | Description |
block | block.tpl.php | Default block implementation. |
block__REGION | block--REGION.tpl.php | REGION is replaced with the theme region name, and the template targets blocks in that region. |
block__MODULE | block--MODULE.tpl.php | MODULE is replaced with the name of the module that created the block. For example, a template file that targets custom blocks would be block--block.tpl.php and a block created by the menu module would be targeted by using block--menu.tpl.php. |
block__MODULE__DELTA | block--MODULE--DELTA.tpl.php | The DELTA value, which used to be a number in previous versions, is the system name of the block as defined by the module. For example, to target the System module’s Navigation block, you would use block-- system--navigation.tpl.php. In this example, “system” is the module and “navigation” is the delta. |
Some observations of $theme_hook_suggestions include:
• Underscores are used instead of dashes.
• File extensions are not present because these hooks can be implemented as theme
functions or template files. At this stage in the process, it doesn’t matter whether a
template or a theme function will be used. When it’s time to render the content,
theme() will determine which should be used and make the necessary adjustments.
• Each suggestion begins with a hook__ (double-underscore) prefix. In the example
shown in Listing 15–15, that hook is block. This allows Drupal to fall back on the
generic theme hook, which in this case is block, and use block.tpl.php when a
more specific template, like block--module.tpl.php, doesn’t exist.
Suggestions and Template Function
以theme_links()为例:
Suggestion | Theme Function Equivalent | Description |
links | THEME_links() | Default implementation, which is used for all implementations unless a more specificimplementation like those below is specified. |
links__node | THEME_links__node() | Targeted implementation of theme_links() that only applies to links lists inside of nodes. |
links__comment | THEME_links__comment() | Targeted implementation of theme_links() that only applies to links lists inside of comments. |
links__contextual | THEME_links__contextual() | Targeted implementation of theme_links() that only applies to links generated for contextual links. |
links__contextual__node | THEME_links__contextual__node() | Targeted implementation of theme_links() that only applies tocontextual links inside of nodes. |
You’ll notice in Drupal’s default page.tpl.php file, located in the modules/system directory, that boththe main and secondary menus are printed using suggestions. You might also notice that theme functions called theme_links__system_main_menu() and theme_links__system_secondary_menu() do not exist, and that’s okay. In this case, the base hook, or the fallback, theme_links() will be used unless a more targeted theme function is created (see Listing 15–16).
Listing 15–16. Excerpt from modules/system/page.tpl.php
<?php if ($main_menu || $secondary_menu): ?>
<div id="navigation"><div class="section">
<?php print theme('links__system_main_menu', array('links' => $main_menu, 'attributes'
=> array('id' => 'main-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' =>
t('Main menu'))); ?>
<?php print theme('links__system_secondary_menu', array('links' => $secondary_menu,
'attributes' => array('id' => 'secondary-menu', 'class' => array('links', 'inline',
'clearfix')), 'heading' => t('Secondary menu'))); ?>
</div></div> <!-- /.section, /#navigation -->
<?php endif; ?>