Creating a page template for a content type gives you a lot of control over the structure of the page. While Drupal will automatically pick up a node template for a content type, if you use the right naming convention, it will not for a page template. Fortunately it just takes a few lines of code and you can create a page template for any content type you choose.

Before we start, let’s take a brief look at the difference between a node and a page template.

  • Page: the template that controls the whole page. This will include a $content variable, which after rendering will be the node.
  • Node: the template that controls just the content part of the page.

Implement a preprocess hook in template.php

To tell Drupal to use the page template for a content type, you can use template_preprocess_page. This hook is used whenever a page.tpl.php template is used to preprocess variables for it.

In this case, you are going to use template_preprocess_page to tell Drupal to use a specific page template for a specific content type, instead of the default page.tpl.php.

Here is an example of telling Drupal to use a template for a content type. Add this code to the template.php in your theme, and change THEME to the name of your theme. If you have already implemented theme_preprocess_page in your theme’s template.php, you can add the ‘if’ statement to that.

function THEME_preprocess_page(&$variables) {
  if ($variables['node']->type == 'article') {
    $variables['theme_hook_suggestions'][] = 'page__article';
  }
}

In this example, I’m telling Drupal that I’d like to use the page__article template if the node type is article. This is added to 'theme_hook_suggestions', which adds it to the pool of potential templates that Drupal can use. In most cases it will use this one, unless you have another template that meets a more specific criteria. For example, you might have a page template for a single node, which would be more specific and used instead.

In the example above, you are explicitly mapping a template to a content type. But what if you want the option to add a page template for any content type that you use now and in the future?

Fortunately you can adjust the snippet above to do just that.

function THEME_preprocess_page(&$variables) {
  if (isset($variables['node']->type)) {
    $variables['theme_hook_suggestions'][] = 'page__' . $variables['node']->type;
  }
}

Have a look at this part:

'page__' . $variables['node']->type;

This means that there will be a template suggestion added for all node types. If you have two content types, article and recipes, you can use the following templates:

'page--article';
'page--recipe';

Note that the actual template filename uses hyphens while the theme_hook_suggestions uses underscores.

You can inspect the 'theme_hook_suggestions' array on any path and see which page templates are included.

function TEMPLATE_preprocess_page(&$variables) {
  if (isset($variables['node']->type)) {
    $variables['theme_hook_suggestions'][] = 'page__' . $variables['node']->type;
	dpm($variables);
  }
}

The dpm() will return the following:

Drupal 7 theme hook suggestions

You can see page__article in the array. If you decided you want to create a page template for a specific node, you could do that by creating a template with the name page__node__id and change id to the node ID. This would be used instead of the page__article template. In the example above, this was called on a node with a NID of 420 on my local site. So if I wanted a page template for that node, I’d create a template file called page--node--420.tpl.php

Wrapping up

Using specific page templates for content types is incredibly handy if you want to change the structure of the page. While Drupal doesn’t automatically pick up templates for content types, you can add in template.php with just a few lines of code.