Different page templates depending on URL aliases

Last modified: June 18, 2009 - 15:24

The list of "template suggestions" for a template can be modified in your template.php file. The following snippet will add page template suggestions for each level of URL alias for the current page. That allows you to, for example, define page-music.tpl.php template which would apply to every page under 'music' path / logical directory. (This information is of particular importance to users of pathauto module who want to create, say, a landing page using a different tpl.php file.)

Drupal 5 version:

<?php
function _phptemplate_variables($hook, $vars = array()) {
  switch (
$hook) {
    case
'page':
   
     
// Add page template suggestions based on the aliased path.
      // For instance, if the current page has an alias of about/history/early,
      // we'll have templates of:
      // page-about-history-early.tpl.php
      // page-about-history.tpl.php
      // page-about.tpl.php
      // Whichever is found first is the one that will be used.
     
if (module_exists('path')) {
       
$alias = drupal_get_path_alias(str_replace('/edit','',$_GET['q']));
        if (
$alias != $_GET['q']) {
         
$suggestions = array();
         
$template_filename = 'page';
          foreach (
explode('/', $alias) as $path_part) {
           
$template_filename = $template_filename . '-' . $path_part;
           
$suggestions[] = $template_filename;
          }
        }
       
$vars['template_files'] = $suggestions;
      }
      break;
  }
 
  return
$vars;
}
?>

Drupal 6 version:
<?php
function phptemplate_preprocess_page(&$vars) {
  if (
module_exists('path')) {
   
$alias = drupal_get_path_alias(str_replace('/edit','',$_GET['q']));
    if (
$alias != $_GET['q']) {
     
$suggestions = array();
     
$template_filename = 'page';
      foreach (
explode('/', $alias) as $path_part) {
       
$template_filename = $template_filename . '-' . $path_part;
       
$suggestions[] = $template_filename;
      }
     
$vars['template_files'] = array_merge((array) $suggestions, $vars['template_files']);
    }
  }
}
?>

Variations
The following are a couple of variations on this idea.

Change only a CSS class in a page template. Works for making changes in CSS that don't need a different template

<?php
   
if (module_exists('path')) {
       
$alias = drupal_get_path_alias($_GET['q']);
       
$class = explode('/', $alias);
        print
'<div class="page page-'.$class[0].'">';
    }
?>

Limit changes for a specific node type:

<?php
     
// (...)
     
if(arg(0)=='node') {
         
$vars['template_files'] = 'page_' . $vars['node']->type;
     }
    
// (...)
?>

Different page templates depending on CCK content type

beanmac - June 5, 2008 - 21:35

Drupal 6 version

The list of "template suggestions" for a template can be modified in your template.php file. The following snippet uses code from the template_preprocess_page (http://api.drupal.org/api/function/template_preprocess_page) function to check a content type which page-CCK content type.tpl.php files can be used.
Note: You have to install and configure CCK first before the content type condition will work, else it will ignore it.

<?php

    $i
= 0;
   
$suggestion = $template_filename = 'page';
   
$content_type = $vars['node']->type;
   
$suggestions = array();
   
    while (
$arg = arg($i++)) {
       
$suggestions[] = $suggestion .'-'. $arg;
        if (!
is_numeric($arg)) {
           
$suggestion .= '-' . $arg;
        }
    }

   
// Check if content type is set and compare that content type is not a the default 'page'
   
if (isset($content_type) && strcmp($template_filename, $content_type) <> 0) {
       
$suggestions[] = $template_filename . '-' . $content_type;        
    }

    if (
drupal_is_front_page()) {
       
$suggestions[] = 'page-front';
    }

    if (
$suggestions) {
       
$vars['template_files'] = $suggestions;
    }
?>

So far, this snippet has been working!

default template when accessed without alias

Waruna - June 11, 2008 - 12:17

Slight modification

When accessed through normal URL ( without alias ) pages is shown with default template.

eg:
http://domain.com/?q=music/node/1 - uses the page-music.tpl.php
http://domain.com/?q=node/1 - uses the page.tpl.php

Line if ( $alias != $_GET['q'] ) replaced if ( $alias != $_GET['q'] && $alias == $_REQUEST['q'] )

<?php
function _phptemplate_variables($hook, $vars = array())
{
   switch (
$hook)
  {
    case
'page':
  
     
// Add page template suggestions based on the aliased path.
      // For instance, if the current page has an alias of about/history/early,
      // we'll have templates of:
      // page-about-history-early.tpl.php
      // page-about-history.tpl.php
      // page-about.tpl.php
      // Whichever is found first is the one that will be used.
     
     
if (module_exists('path'))
      {
       
$alias = drupal_get_path_alias(str_replace('/edit','',$_GET['q']));
       
        if (
$alias != $_GET['q'] && $alias == $_REQUEST['q'] )
        {
           
$suggestions = array();
           
$template_filename = 'page';
            foreach (
explode('/', $alias) as $path_part)
            {
               
$template_filename = $template_filename . '-' . $path_part;
               
$suggestions[] = $template_filename;
            }
        }
       
       
$vars['template_files'] = $suggestions;
      }
      break;
  }
//switch

 
return $vars;
}
?>

If you are creating your own

manorius - October 1, 2008 - 05:00

If you are creating your own ZEN subtheme under Drupal 5, implement
the D6 snippet instead of the D5 and it should work like a dream.

to use with page-front.tpl.php

er0k - December 2, 2008 - 18:20

using the above snippet for Drupal 6.x disabled my page-front.tpl.php. Use this slight modification to fix:

<?php
function phptemplate_preprocess_page(&$vars) {
  if (
module_exists('path')) {
   
$alias = drupal_get_path_alias(str_replace('/edit','',$_GET['q']));
    if (
$alias != $_GET['q']) {
     
$suggestions = array();
     
$template_filename = 'page';
      foreach (
explode('/', $alias) as $path_part) {
       
$template_filename = $template_filename . '-' . $path_part;
       
$suggestions[] = $template_filename;
      }
     
$vars['template_files'] = $suggestions;
    }
  }
}
?>

where to put the template file suggestions

n33x - May 20, 2009 - 20:16

I am not clear on where to place the file names in the 6.x version.

would it be possible to expand on that? It seems that the 5.x version has an example.

I am running 6.x

thanks

Merge new suggestions with default suggestions

mtwesley - December 28, 2008 - 06:35

I found it helpful to merge the two arrays so that I could keep the default suggestions as a fallback option:

<?php
   
// ...
   
}
   
$vars['template_files'] = array_merge((array) $suggestions, $vars['template_files']);
  }
 
// ...
?>

@ mtwesley: You are a

anotherdave - March 25, 2009 - 14:01

@ mtwesley:

You are a lifesaver - cheers mate. This is exactly what I needed to do & wasn't awake enough this morning to realise it til I saw you post it!

Thank you!

Dave

Breaks update.php if implemented as module

cultiv8 - May 7, 2009 - 20:06

As a note, if you implement the D6 snippet as a module (ie not in template.php), it will work but it will break update.php.

 
 

Drupal is a registered trademark of Dries Buytaert.