Skip to content Skip to navigation

Using Templates in a Custom Drupal Module

In Drupal development land, the theme is what controls the final HTML, CSS, and Javascript that get delivered to the browser.

Sometimes, however, in developing a custom module, you want to provide a suggestion for an HTML framework, and not rely on the theme's default implementation of a given block of HTML.

You may ask yourself:

Can I use .tpl.php files in a Drupal module?

(And you may ask yourself, "How do I work this?", and you may ask yourself, "Where is that large automobile?")

Enter hook_theme_registry_alter()

Drupal's API includes a nifty function named hook_theme_registry_alter(). This hook allows you to - wait for it - alter the theme registry. The theme registry "maintains cached data on the available theming hooks and how to handle them". By altering the theme registry, you can tell Drupal to look elsewhere for theme templates (e.g., *.tpl.php files).

See What's in the Theme Registry

  1. Install and enable the Devel module
  2. Call dpm($theme_registry) in your custom module:

    function mymodule_theme_registry_alter(&$theme_registry) {
      dpm($theme_registry);
    }
                   
  3. Clear your theme-registry cache: drush cc theme-registry

  4. Reload the page, and you then get a nice Krumo display of the entire $theme_registry array.

    Screenshot of a Krumo output of the $theme_registry variable

  5. In this case, we want to override the search page "no results" language (which has been the subject of contentious debate) with a custom template.
    Screenshot of the default Drupal search page for no results found
  6. $theme_registry['search_results'] looks like this:

    Array
    (
        [variables] => Array
            (
                [results] =>
                [module] =>
            )

        [file] => search.pages.inc
        [template] => modules/search/search-results
        [type] => module
        [theme path] => modules/search
        [includes] => Array
            (
                [0] => modules/search/search.pages.inc
            )

        [preprocess functions] => Array
            (
                [0] => template_preprocess
                [1] => template_preprocess_search_results
                [2] => contextual_preprocess
            )

        [process functions] => Array
            (
                [0] => template_process
                [1] => rdf_process
            )

    )

    Screenshot of a Krumo output of just the $theme_registry['search_results'] array

Alter the Theme Registry

We're going to override that setting in the theme registry, and tell the theme system to look in our custom module (named "mymodule") for a template:

function mymodule_theme_registry_alter(&$theme_registry) {
  // tell the theme system to look in the "templates" subdirectory within our module directory
  $theme_registry['search_results']['theme paths'] = array(0 => drupal_get_path('module', 'mymodule') . '/templates');
  $theme_registry['search_results']['theme path'] = drupal_get_path('module', 'mymodule') . '/templates';
  $theme_registry['search_results']['path'] = drupal_get_path('module', 'mymodule') . '/templates';
  // tell the theme system to use 'search-results.tpl.php' as the template file. Note that you do not include 'tpl.php'
  $theme_registry['search_results']['template'] = 'search-results';
}

Our search-results.tpl.php file looks like this:

<?php
$content = '<ul>';
$content .= '<li>' . t('Check if your spelling is correct.') . '</li>';
$content .= '<li>' . t('Simplify your search by using fewer words.') . '</li>';
$content .= '<li>' . t('Remove quotes around phrases to match each word individually: %stanfordquote will match less than %stanfordnoquote.', array('%stanfordquote' => '"stanford university"', '%stanfordnoquote' => 'stanford university')) . '</li>';
$content .= '<li>' . t('Consider loosening your query with <em>OR</em>: <em>stanford university</em> will match less than <em>stanford OR university</em>.') . '</li>';
$content .= '</ul>';
?>
<?php if ($search_results): ?>
  <h2><?php print t('Search results');?></h2>
  <ol class="search-results <?php print $module; ?>-results">
    <?php print $search_results; ?>
  </ol>
  <?php print $pager; ?>
<?php else : ?>
  <h2><?php print t('Your search did not yield any results');?></h2>
  <?php print $content; ?>
<?php endif; ?>

The Results

Now our $theme_registry['search_results'] looks like this:

Array
(
    [variables] => Array
        (
            [results] =>
            [module] =>
        )

    [file] => search.pages.inc
    [template] => search-results
    [type] => module
    [theme path] => sites/all/modules/mymodule/templates
    [includes] => Array
        (
            [0] => modules/search/search.pages.inc
        )

    [preprocess functions] => Array
        (
            [0] => template_preprocess
            [1] => template_preprocess_search_results
            [2] => contextual_preprocess
        )

    [process functions] => Array
        (
            [0] => template_process
            [1] => rdf_process
        )

    [theme paths] => Array
        (
            [0] => sites/all/modules/mymodule/templates
        )

    [path] => sites/all/modules/mymodule/templates
)

Screenshot of a Krumo output of just the $theme_registry['search_results'] array, after it has been altered

And our search results page looks like this:

Screenshot of the modified Drupal search page for no results found

Note that "bike shed" has been replaced by "stanford university"

See Also

Categories: