Eternalistic Designs

The Power of template.php

A few techniques to help your designers.

Jan 02, 2008
8 comments
Submitted By: Fredric Mitchell
Filed Under:
Share our glory:

Theming a fresh Drupal site always gives the designers true glory. Well, its time that I help out my fellow programmers. After all, without us, its just a pretty drupal core.

First things first. I'm assuming that you and the designer are working on a clean theme, like zen. I'm also assuming the use of Drupal 5. Most of the code is available via drupal.org.

So what kinds of things can you do?

Custom id and class tags

The most important thing to know is that Drupal allows the modification of theme functions within this file. This means any function within a module or within the Drupal core that begins with name theme_xxx can be hooked into and modified to include elements to assist the designer, i.e. adding 'id' or 'class' tags.

Let's say, for example, you'd like to modify the menu items. Your designer wants to be able to add special attributes to each menu item, but needs a unique id tag for each list element. Because there is a theme_menu_item function in the core menu.inc file, we can simply create a phptemplate_menu_item function in template.php that overrides how the menu item is displayed. This avoids touching the actual core function (a big no-no in Drupaland) and keeps our mods in one location as upgrades are performed, assuming your template.php file is in the sites -> default -> themes directory (which it should be).

To add custom id tags to each menu item, as well as add an 'active' class when the user is on that particular page, try:

 
/**
* Implementation of theme_menu_item().
*
* Add active class and custom id to current menu item links.
*/
function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) {
  $item = menu_get_item($mid); // get current menu item
  // decide whether to add the active class to this menu item
  if ((drupal_get_normal_path($item['path']) == $_GET['q']) // if menu item path...
  || (drupal_is_front_page() && $item['path'] == '<front>')) { // or front page...
    $active_class = ' active'; // set active class
  } else { // otherwise...
    $active_class = ''; // do nothing
  }
  $attribs = isset($item['description']) ?
array('title' => $item['description']) : array();
  $replace = array(' ', '&');
  $attribs['id'] = 'menu-'. str_replace($replace, '-', strtolower($item['title']));
  return
'
<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) .
$active_class .'" id="'. $attribs['id'] . '">' .
menu_item_link($mid) . $children ."</li>
\n";
}
 

The key to this function is the line:

 $attribs['id'] = 'menu-'. str_replace($replace, '-', strtolower($item['title']));

This creates a value in the $attributes array with a key of 'id' equal to the value of string 'menu-' concatenated to the actual name of the menu item. As long as each menu item has a unique name, a unique id is generated and the style can be crafted accordingly.

Different designs for different pages

Maybe you have a front 'splash' page, a 'home' page, and then the rest of your site. This is typically true for new startups providing a web service. You'd like new visitors to have a very simple experience showcasing your service, logged-in users to have an array of links to choose from, and something different once users are using the service.

By default, pages and nodes will use the page.tpl.php and node.tpl.php, respectively. To have your 'front' and 'home' pages use a different template file, you need something to translate what page the user is on (via the url) and select the appropriately named file. As outlined in the theme developer's guide of drupal.org, the template.php file can accomplish this within the _phptemplate_variables() function, specifically within the switch case of 'page'. If you're using the localization module, you'll want to edit the function slightly to allow for the prepend of the language:

 
      if (module_exists('path')) {
        $alias = drupal_get_path_alias($_GET['q']);
        if ($alias != $_GET['q']) {
          $suggestions = array();
          $template_filename = 'page';
          $alias = explode('/', $alias);
          array_shift($alias);
          foreach ($alias as $path_part) {
            $template_filename = $template_filename . '-' . $path_part;
            $suggestions[] = $template_filename;
          }
        }
        $vars['template_files'] = $suggestions;
      }
 

Views Theme Wizard

As you create your views, customization can add more depth to your design. Although you may want to create multiple views that group by specific elements, each view doesn't need to look the same even if they function the same. An example would be creating a view that showcases events and groups them by date and one that showcases events and groups them by category.

Answer: Use the views theme wizard. This function automatically generates the proper code for you to place inside your template.php file and create the proper template files for your designer to manipulate.



References:

Make people smarter:

Formatting

Would it be possible for you to reformat the code display on this page for readability? It is currently putting the code in a single line. I've tried Firefox, Safari and IE6.

This request in no way diminishes my respect and appreciation for your work!

 

Moo. Moo moo.

Sorry.  My fault.  I went to tinker with one little thing on Fredric's post and ended up blowing the formatting all to hell. 

Thanks

Nice taste of the possibilities.

A useful addition to a

A useful addition to a valuable, growing list of articles :)  A question and a comment:

 - Does phptemplate_menu_item() need to be refernced in a special way from *.tpl.php? Or will it intercept menu rendering automatically?

 - From Drupal 5.x onwards, I don't think the template.php edit is required to use individual node-<type>.tpl.php (as long as you follow Drupal/PHPTemplate's naming convention).

 

Thanks

The template files (*.tpl.php) do not directly interact with your theme hooks. The theme hooks essentially allow you to modify how certain functions with a module are displayed, i.e. allowing you to add attributes to a link or output for your designer to modify them in css, not in the *tpl.php files.

I'm not sure about your second point. By naming conventions, you mean the naming of your template files? Is that convention outlined somewhere?

Communication breakdown...

I think maybe theneemies is thinking about this:

 

http://drupal.org/node/104316

template naming convention

That handbook page gets started on using different *.tpl.php files, if I find more comprehensive documentation I'll post it back here. Essentially, if you use the following conventions, PHPTemplate automatically picks up your *.tpl.php files without explicitly calling them in template.php:

page-front.tpl.php (for a custom front page)

node-[type].tpl.php (for each content type)

node-[nid].tpl.php (for an individual node)

node-edit.tpl.php (for edit view)

etc.

bonus tip

check out this tip i found regarding removing tabs via template.php

http://www.innovatingtomorrow.net/2008/02/18/removing-and-altering-tab-n...

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <iframe> <img><br/><br /><span><p><blockquote> <table><tr><td><tbody><th>
  • Lines and paragraphs break automatically.
  • You may post block code using <blockcode [type="language"]>...</blockcode> tags. You may also post inline code using <code [type="language"]>...</code> tags.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options