4 min read

Drupal 7: Defining template files tpl.php and theming hooks

To simplify the life of Drupal themers, Drupal has a template system. It can be extended using the hook_theme().

A theming hook defined in the hook_theme function can later be overridden in a theme through a theme function or template file. Here’s how to define it in a module named example_template:

function example_template_theme() {
  return array(
    'custom_template' => array( // name of the theming hook
      'variables' => array( // variables available in the template
        'body' => NULL,
        'title' => NULL,
      ),
    ),
  );
}

Now, to use this theming hook, you should call it like this:

theme('custom_template', array('body' => 'Some body', 'title' => 'Some title'));

The first parameter is the name of the theming hook, and the second parameter is an array of variables defined for this hook.

In your module, define either a default theme function or a template that will be used. To do this, create a function named theme_THEMING_HOOK_NAME():

Defining the function in your module:

function theme_custom_template($variables) {
  $output = '<div class="custom-template-wrapper">';
  $output .=    '<div class="body">';
  $output .=      $variables['body'];
  $output .=    '</div>';
  $output .=    '<div class="title">';
  $output .=      $variables['title'];
  $output .=    '</div>';
  $output .= '</div>';
  return $output;
}

To use a template file from your module as the default, you need to specify the template location in hook_theme():

function example_template_theme() {
  return array(
    'custom_template' => array(
      'variables' => array( // variables available in the template
        'body' => NULL,
        'title' => NULL,
      ),
      // template name, in this case custom_template.tpl.php in module root
      'template' => 'custom_template',
    ),
  );
}

After defining this theming hook, you can override it in any theme:

function MYTHEME_custom_template($variables) {
  $output = '<div class="mytheme-custom-template-wrapper">';
  $output .=    $variables['title'] . ' - ' . $variables['body'];
  $output .= '</div>';
  return $output;
}

To use a template instead of a function, create a template file named example_template.tpl.php and place it in the theme folder or inside the theme’s templates subfolder.

IMPORTANT! You cannot use both a theme function and a template simultaneously. The theme function has higher priority and will always be used if defined.

Complete code:

/**
 * @file
 * Example template
 */

/**
 * Implements hook_menu().
 */
function example_template_menu() {
  $items['example_template'] = array(
    'title' => 'Example template',
    'page callback' => 'example_template_callback',
    'access callback' => TRUE,
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Implements hook_theme().
 */
function example_template_theme() {
  return array(
    'custom_template' => array( // name of the theming hook
      'variables' => array( // variables available in the template
        'body' => NULL,
        'title' => NULL,
      ),
      // template name, custom_template.tpl.php in module root
      'template' => 'custom_template',
    ),
  );
}

/**
 * Page callback.
 */
function example_template_callback() {
  return theme('custom_template', array('body' => 'Some body', 'title' => 'Some title'));
}

/**
 * Returns HTML for a custom template.
 *
 * @param $variables
 *   An associative array containing:
 *   - body: body text.
 *   - title: title text.
 *
 * @ingroup themeable
 */
function theme_custom_template($variables) {
  $output = '<div class="custom-template-wrapper">';
  $output .=    '<div class="body">';
  $output .=      $variables['body'];
  $output .=    '</div>';
  $output .=    '<div class="title">';
  $output .=      $variables['title'];
  $output .=    '</div>';
  $output .= '</div>';
  return $output;
}