http://drupal.org/node/223440
Task · How to work with template suggestions · Themers · Drupal 6.x
Last modified: August 26, 2009 - 03:05
Template suggestions are alternate templates based on existing .tpl.php files. These suggestions are used when a specific condition is met and a matching file exists. All layers from core, modules, theme engines and themes can provide the suggestions. You can think of them as naming hints telling the system to pick and choose based on the right circumstances. The idea is simple but it is a powerful feature providing another layer of customization.
Devel module showing template suggestions for the possible "page" templates.
A listing of all the suggestions for core can be found in Core templates and suggestions.
These naming suggestions are set from preprocess functions. There are plenty already provided by core. If you need to extend it further, add a preprocessor for the theming hook into your template.php file. This example add suggestions on the "page" theming hook. It can be added to any hook implemented as a template.
The prefix of "drop" should be the name of your theme.
<?php
function drop_preprocess_page(&$variables) {
global $user;
// Add a single suggestion.
if (module_invoke('throttle', 'status') && isset($user->roles[1])) {
$variables['template_file'] = 'page-busy';
}
// Add multiple suggestions.
if (!empty($user->roles)) {
foreach ($user->roles as $role) {
$filter = '![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s';
$string_clean = preg_replace($filter, '-', drupal_strtolower($role));
$variables['template_files'][] = 'page-'. $string_clean;
}
}
}
?>
There are two ways to add these suggestions.
- The key of '
template_file' accepts a single suggestion and it takes precedence. If the condition is met and the file exists, it will be used ignoring all others. - The key of '
template_files' (plural) can accept an array of suggestions. They are processed in FILO order (first in last out order). Adding to the array should be done with a general condition first, progressively getting more specific so it cascades based on specificity.
With the above example, Drupal will attempt to use a file named "page-busy.tpl.php" when the throttling threshold is met for anonymous users (anonymous role id typically set to 1). The others inform Drupal to look for templates based on the roles assigned to the current user, e.g., "page-authenticated-user.tpl.php". If none apply, the base template of "page.tpl.php" is used.
These are simply examples. You can set any context based on any data available to you.
A few notes:
-
When adding to '
template_files', add to the array. Do not reset it since the variables are passed by reference. All the suggestions set before it in core and modules would be lost.<?php
// Do not do this:
$variables['template_files'] = array('hook-suggestion');
// Instead do this:
$variables['template_files'][] = 'hook-suggestion';
?> - Prefix the suggestion with the name of the hook it is associated with. This keeps it clear and the files grouped together. It also minimizes any chance of Drupal registering the template with a different hook.
- Use hyphens instead of underscores for consistency. The main template will never use underscores.
- Suggestions work only when it is placed in the same directory as the base template. Templates can be placed in any sub-directory of the theme. They must be paired into the same location.
- The theme registry does not have to be cleared for suggestions. It's only the base template that needs to be registered. Suggestions are discovered on the fly.
‹ The theme registry for special cases up Core templates and suggestions ›
» Login or register to post comments
Allow template suggestion based on URL path and node type.
TimG - August 28, 2008 - 05:38
What I wanted to do was to have a templates based on the path. So, www.example.com/portfolio would call page-portfolio.tpl.php and page.tpl.php for the rest of the site. In addition, I wanted to specify a different template based on www.example.com/blog. Which calls the templates differently I guess because it's a node type of "blog" instead of a regular old "page"? I think?!? I'm not sure, I'm pretty new to Drupal and am just getting started.
Anyway, I learned I needed to be able to specify template based on node type in addition to path type. So, this is the script that I cobbled together from the script above and some script someone on IRC was generous to provide.
Like I said, I'm new to Drupal and PHP actually, so I'm sure there is a better way to do this. But, here it is anyways for anyone who would like to do something similar. It took me a lot of sleuthing to find all the pieces for this code! This code should go in your template.php file and your blog template should be named page-blog.tpl.php. Enjoy! =)
<?php
function phptemplate_preprocess_page(&$variables) {
global $user;
if (module_exists('path')) {
//allow template suggestions based on url paths.
$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;
}
$alias_array = explode('/', $alias);
$variables['template_files'] = $suggestions;
}
// Add a single suggestion.
if (module_invoke('throttle', 'status') && isset($user->roles[1])) {
$variables['template_file'] = 'page-busy';
}
// Add multiple suggestions.
if (!empty($user->roles)) {
foreach ($user->roles as $role) {
$filter = '![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s';
$string_clean = preg_replace($filter, '-', drupal_strtolower($role));
$variables['template_files'][] = 'page-'. $string_clean;
}
if (drupal_is_front_page()) {
$variables['template_file'] = 'page-front';
}
}
}
}
?>
Login or register to post comments
Thanks.. I dropped a simpler
mfb - September 2, 2008 - 23:57
Thanks.. I dropped a simpler function into a theme to just get page templates based on path aliases:
<?php
function phptemplate_engine_preprocess_page(&$variables) {
$alias = drupal_get_path_alias($_GET['q']);
if ($alias != $_GET['q']) {
$template_filename = 'page';
foreach (explode('/', $alias) as $path_part) {
$template_filename = $template_filename . '-' . $path_part;
$variables['template_files'][] = $template_filename;
}
}
}
?>
Login or register to post comments
Theming a page by content type
keathmilligan - October 6, 2008 - 06:13
Create a page template file for the content type you want to theme. For example, "page-node-my_content_type.tpl.php". Replace "my_content_type" with your content type obviously.
Now add the following to your template.php:
<?php
function my_theme_preprocess_page(&$variables) {
if ($variables['node']->type == "my_content_type") {
$variables['template_files'][] = 'page-node-my_content_type';
}
}
?>
Replace "my_theme" with the name of your theme and again, "my_content_type" with the name of your content type.
Go to Site Configuration | Performance and clear your cache. Now nodes of the specified content type will get their own page template when viewed as a page.
Login or register to post comments
Theming multiple content types
JonMB - October 21, 2008 - 16:21
Just adding onto your code for theming multiple content types:
<?php
function my_theme_preprocess_page(&$variables) {
if ($variables['node']->type == "my_content_type") {
$variables['template_files'][] = 'page-node-my_content_type';
} elseif ($variables['node']->type == "my_content_type_2") {
$variables['template_files'][] = 'page-node-my_content_type_2';
} elseif ($variables['node']->type == "my_content_type_3") {
$variables['template_files'][] = 'page-node-my_content_type_3';
} elseif ($variables['node']->type == "my_content_type_4") {
$variables['template_files'][] = 'page-node-my_content_type_4';
}
}
?>
In this example I have four different content types with four different themes.
Login or register to post comments
exclude node add and edit pages
kgp22 - December 8, 2008 - 17:43
if ($variables['node']->type == "my_content_type" && arg(2)!='edit' && arg(1) !='add') {
$variables['template_files'][] = 'page-node-my_content_type';
}
This could help if you don't want same layout when you add/edit the page content.
Login or register to post comments
I try ,but it didn't
ddd2500 - March 15, 2010 - 10:04
I try ,but it didn't work.
and I use the grand to define my new theme...
Login or register to post comments
Theming a page by arbitrary content types
khonggiannet - November 10, 2008 - 16:30
You could improve above code to have the theme suggestion for all content types in your site.
<?php
function my_theme_preprocess_page(&$variables) {
if ($variables['node']->type != "") {
$variables['template_files'][] = "page-node-" . $variables['node']->type;
}
}
?>
Now just make your template in form page-node-your_content_type. If it's missing, the default page template will be used.
Login or register to post comments
Works for me!
benahlquist - August 27, 2009 - 18:59
This is probably the cleanest solution I've found. Thanks a bunch all of you, especially khonggiannet. I mean, who really wants to manually add content types when you've built this slick little autodetect-type of system?
Nice work!
Ben Ahlquist
IDEaS Computers
http://www.ideascomputers.com
----------------------
Quality Forum Posts & Replies since 1996.
Login or register to post comments
Content Type Agnostic
doublejosh - December 3, 2009 - 23:06
Yeah, I too opted for the type agnostic option that just adds the suggestion and can be "turned on and off" by creating the temple or removing it.
function MY-THEME_preprocess_page(&$variables) {
$variables['template_files'][] = 'page-node_'.$variables['node']->type;
}
Pretty slim.
Login or register to post comments
not working
comterkumar - September 16, 2009 - 04:31
I have done all these
Still this is not working for me
I am using drupal 6 version
Please help me
VBKUMAR
Nandakumar
Comter Systems Inc
Login or register to post comments
Try using khonggiannet's
docillenstein - September 20, 2009 - 19:27
Try using khonggiannet's solution above. Use it in your template.php by itself - temporarily take out the other code in the preprocess_page area - to test it out. In my case it was a matter of taking out everything in function atck_preprocess_page($vars)
I tried the code alone and things worked for me, then I adjusted it to match the rest of the setup on the ATCK template. I switched his $variables to $vars like everything else, and put it in the mix with the rest right before the last line to output the results.
The process went like so:
I copied the code above
<?php
function my_theme_preprocess_page(&$variables) {
if ($variables['node']->type != "") {
$variables['template_files'][] = "page-node-" . $variables['node']->type;
}
}
?>
and reduced it to
if ($vars['node']->type != "") {
$vars['template_files'][] = "page-node-" . $vars['node']->type;
}
and slid it in to the larger block of code like this
function atck_preprocess_page($vars) {
$vars['styles'] .= atck_ie_styles();
// Determine if the page is the front page and apply pertinent classes
// if it is. Otherwise use that arg variables to construct the class and
// id names.
switch (TRUE) {
case ($vars['is_front']):
$body_id = '>
/* <![CDATA[ */
var submitInfoForm = function()
{
function validateForm() {
//return true for now
return true;
}
if(validateForm()) {
jQuery('#form_wrap').load
(
jQuery('#requestInfoForm').attr('action'),
jQuery('#requestInfoForm').serializeArray()
);
};
}
/* ]]> */
</script>