Welcome to the first in what we hope will be a ongoing series of blogs that discuss the more technical side of things. Today I'd like to talk about how we theme template calls in Drupal 6, and how much it has changed from the way we did it in Drupal 5. The Theory Let's dive right in. At its most basic level a website is built from a collection of files and database entries. These files are separated into several layers, so that it is easier to make changes to the application in the future. These layers consist of:

  • Content - the raw data that gets displayed on a page. In a CMS like Drupal, this is stored in the database.
  • Functionality - The logic that decides which content gets displayed and how it interacts with other data
  • Form - the HTML
  • Presentation - the CSS

The benefit of this separation is that we can make changes in one layer without affecting the others. At CommonPlaces, we strive to separate markup into individual templates with the site logic (or Functionality) remaining in template.php. How We Did It In D5 With Drupal 5, in any of our template.php functions, we would often find ourselves needing to include markup in our variables. To remove the HTML into a separate layer, we used a function and a template. In order to pass the variables to a template, we used the function _phptemplate_callback. For example:

function _phptemplate_variables($hook, $vars) {
  global $user;
  if ($vars['type'] == 'mytype' || $vars['type'] == 'mytype2' || $vars['type'] == 'mytype3') {
    if ($user->uid > 0) {
      $links = array(
        'add_mytype' => l(t('Create a MyType'), 'node/add/mytype', array('title'=>'Create a MyType'), 'destination='.drupal_get_destination()),
        'add_mytype2' => l(t('Share an MyType2'), 'node/add/mytype2', array('title'=>'Share an MyType2'), 'destination='.drupal_get_destination()),
        'add_mytype3' => l(t('Share an MyType3'), 'node/add/mytype2', array('title'=>'Share an MyType3'), 'destination='.drupal_get_destination())
    else {
      $links = array(
        'login' => l(t('Login'), 'user', array('title'=>'Login'), 'destination='.drupal_get_destination()),
        'register' => l(t('Register'), 'user/register', array('title'=>'Register'), 'destination='.drupal_get_destination()),
    return _phptemplate_callback('mytype_links', $links);

We would then be able to add any sort of markup we wanted in these line templates. In a file called mytype_links.tpl.php, we could then have the following:

<ul class="tools">
  <?php if ($add_mytype) : ?>
<li class="add_mytype"><?php print $add_mytype; ?></li>

  <?php endif; ?>
  <?php if ($add_mytype2) : ?>
<li class="add_mytype2"><?php print $add_mytype2; ?></li>

  <?php endif; ?>
  <?php if ($add_mytype3) : ?>
<li class="add_mytype3"><?php print $add_mytype3; ?></li>

  <?php endif; ?>

There are several instances where we would use this approach. For example, in a view template function if we want to print elements of loaded node from the node reference, we could create a template with markup for those elements. How To Do It In D6 The fabulous _phptemplate_callback function no longer exists in Drupal 6. In fact the whole templating structure is different. D6 is based on template suggestions and if you need a line template that doesn't fit into that hierarchy, you use theme_render_template and pass it the name of the template file and the variable array:

function mytheme_preprocess_node(&$vars, $hook) {
  if ($vars['type'] == 'blog') {
    $vars['blog_info'] = theme_render_template(path_to_theme().'/blog-info.tpl.php', array());

In a template called blog-info.tpl.php, we could then have this:

<?php if ($terms) : ?>
  <span class="blog-terms">Posted in: <?php print $terms ?></span>
<?php endif; ?>
<span class="blog-date">by <?php print $name?> at <?php print format_date($created, 'custom', 'H:i a')?></span>
<span class="blog-comments"><?php print l('Comments', 'node/'.$nid, array('fragment'=>'comments'))?> (<?php print $comment_count?>)</span>

You can then print the variable $blog_info in your node.tpl.php file.

Reference Links:

 Separate Content from Functionality and Design

Separating Content from Form and Presentation

(NOTE: The above two references don't mention the use of a CMS and its ability to add another separation layer.)

From Drupal.org:

D5 _phptemplate_callback

D6 theme_render_template

D6 Template Suggestions

Leave Your Comment