1

Instead of page.tpl.php, How can I use a custom template in theme? I am using the Zen theme.

In Drupal 6, we will specify it in the theme_preprocess_page(), using the $vars['template_files'][] array. I don't know what to use in Drupal 7.

3 Answers 3

6

The equivalent in Drupal 7 is $variables['theme_hook_suggestions'], which is initialized in template_preprocess_page() using the following code:

  if ($suggestions = theme_get_suggestions(arg(), 'page')) {
    $variables['theme_hook_suggestions'] = $suggestions;
  }

If you want to add suggestions for the template files to use, you should append new suggestions using code similarly to the following one ($variables is the parameter passed to the preprocess functions):

$variables['theme_hook_suggestions'][] = "page__new_suggestion";

You can also add your suggestions before the existing ones, to be sure the template file you are suggesting is used whenever other template files exist.

array_unshift($variables['theme_hook_suggestions'], "page__new_suggestion");

Clearly if the template file your code suggests doesn't exist, one of the other template files will be used.
It is also suggested to prepend the template filename with the type of the template, in this case with "page__"; the underscores used in the suggested filename are converted in hyphens before to check if that file exists.

5
  • Thanks for your answer Mr.Kiamlauno. Yesterday I tried the same but forgot to rename the page__my-custom.tpl.php. Thanks for your input again. I renamced that file to page--my-custom.tpl.php. It is working now.
    – Vinoth
    Aug 11, 2011 at 9:12
  • great answer... clear and thorough. should definitely be accepted Sep 9, 2011 at 15:07
  • 1
    Just to suggest an edit, the $variables['theme_hook_suggestions'] = array_unshift($variables['theme_hook_suggestions'], "page__new_suggestion"); part is wrong, uk.php.net/array_unshift returns an int count of the number of items added to the array - so it should not be reassigned to $variables['theme_hook_suggestions'].
    – Pebbl
    Oct 24, 2012 at 16:04
  • @pebbl That's correct. :)
    – apaderno
    Oct 24, 2012 at 16:10
  • @kiamlaluno np, nice one :) -- +1 shame your answer isn't accepted
    – Pebbl
    Oct 24, 2012 at 16:30
1

Drupal 6

<?php
function themeName_preprocess_page(&$vars, $hook) {
  if (isset($vars['node'])) {
   // If the node type is "blog" the template suggestion will be "page-blog.tpl.php".
   $vars['template_files'][] = 'page-'. str_replace('_', '-', $vars['node']->type);
  }
}
?>

Drupal 7:

<?php
function themeName_preprocess_page(&$vars, $hook) {
  if (isset($vars['node'])) {
  // If the node type is "blog" the template suggestion will be "page--blog.tpl.php".
   $vars['theme_hook_suggestions'][] = 'page__'. str_replace('_', '--', $vars['node']->type);
  }
}
?>
1

Just in case this is useful to anyone else out there that stumbles across this looking for how to specify a custom template in a custom location (i.e. not the templates folder) for Drupal 7... this was what I got working:

/**
 * Helper function to produce a list of custom templates
 * in my code I have this tied up to some directory listing
 * code using file_scan_directory - but I have simplified here 
 */
function _my_module_get_template_array(){
  return array(
    'panels-size2-x1-sliders-x2' 
      => '/sites/all/themes/my_theme/custom/panels-size2-x1-sliders-x2.tpl.php',
  );
}

/**
 * Implementation of hook_preprocess_HOOK().
 */
function my_module_preprocess_node( &$vars ){
  if(isset($vars['node']) && arg(2) != 'edit') {
    $node = $vars['node'];
    /// In my setup certain nodes have a field that defines 
    /// the template from a widget that derives it's values 
    /// from the _my_module_get_template_array function. 
    /// You could obviously totally change all the checking 
    /// logic that follows. The only important line is the
    /// 'theme_hook_suggestions' array assignment:
    if ( isset($node->field_lp_template) ) {
      if ( ($items = field_get_items( 'node', $node, 'field_lp_template' )) ) {
        /// pull out the template value from my field_lp_template field
        $template = drupal_render(
          field_view_value( 
            'node', 
            $node, 
            'field_lp_template', 
            reset($items), 
            array('label'=>'hidden')
          )
        );
        if ( $template ) {
          /// we need to translate hyphens for underscores to be inkeeping with D7
          $vars['theme_hook_suggestions'][] = strtr($template,'-','_');
        }
      }
    }
  }
}

/**
 * Implementation of hook_theme().
 *
 * In the following code we define theme information for each possible
 * template - keyed by the template name. Doing this means we can
 * define a full path to our template (which you can not do in 
 * theme_hook_suggestions alone). By keeping the theme_hook_suggestions
 * name defined above the same as the key in the $theme array below
 * means that we tie both together and Drupal will use this information
 * if there are no other overriding templates found.
 */
function my_module_theme() {
  $theme = array();
  foreach ( my_module_get_template_array() as $template => $path ) {
    /// we need to translate hyphens for underscores to be inkeeping with D7
    $template = strtr($template,'-','_');
    $theme[$template] = array( 
      'render element' => 'node',
      'template' => $path,
    );
  }
  return $theme;
}

Anyway, as I said hope it helps... took me several hours of trying lots of other solutions before getting this one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.