Drupal Zombie

Dezombifying Drupal developers since 2011

    Braaains!
Eat braaains!
News feed

How theming works (maybe): part 1

Submitted by Kieran on

Tags: 

You want to change something on your site. Maybe add a message to a contact form, telling customers that your company loves them to the depths of its soul. (That might be true. Gnats can wade through the souls of many companies.)

You need to find what to change, and where to change it. This can be a challenge in Drupal. It's complicated. Finding where to put code might have you looking for b-r-a-i-n-s.

This article explains how information starts out as raw data, and goes on a Drupally quest to become HTML. The HTML the user sees.

A quest!

The explanation starts here, in part one, with the basic concepts. If there's ever a part two, you'll learn more about the data's journey to fulfillment.

It's best to work backwards, from the goal.

The end of the journey

Here's some simplified Drupalish HTML:

  1. <div id="content" class="column">
  2.   <div class="section">
  3.     <h1 class="title" id="page-title">
  4.       Things zombies like
  5.     </h1>
  6.   </div>
  7.   <div class="content">
  8.     <div class="meta submitted">
  9.       Submitted by <span class="username">Willow</span>
  10.       on Fri, 07/22/2011 - 11:32
  11.     </div>
  12.   <div class="content clearfix">
  13.     <div class="field-name-body>
  14.       <p>Zombies like these things.</p>
  15.       <ul>
  16.         <li>Blood drops on roses,</li>
  17.         <li>Whiskers torn from kittens,</li>
  18.         <li>Brains!</li>
  19.         <li>More brains!</li>
  20.       </ul>
  21.     </div>
  22.   </div>
  23. </div>

Figure 1. Some HTML

Drupal adds lots of containers to HTML. All the <div>s and <span>s are pure containers; they don't do anything but contain other stuff. For example, the author's name on line 9 - Willow - is contained in a <span>, which is inside the <div> on line 8, which is inside the <div> on line 7, which is inside the <div> on line 1. Apply a CSS class to #content (i. e., the element with the id of content, on line 1), and you can affect the look of everything in Figure 1.

Crack open a template

Template files are the heart of Drupal theming. They have names like html.tpl.php, and comment-wrapper.tpl.php. .tpl.php is pronounced "tipple-fip." I don't know who first started saying that. I wouldn't be surprised if it was Emma Jane Hogbin.

Templates are PHP programs. They're HTML with variables. For example, this might be a template for creating HTML about a customer:

  1. <div class="customer">
  2.   <p class="name">
  3.     Name: <?php print $name; ?>
  4.   </p>
  5.   <p class="brain-weight">
  6.     Brain weight: <?php print $brain_weight; ?>
  7.   </p>
  8. </div>

Figure 2. Customer template

Most of this is HTML, but lines 3 and 6 have PHP variables. Whatever values those variables have will show up in the output. For example, if $name was "Xander" and $brain_weight was 2.8, the output would be:

  1. <div class="customer">
  2.   <p class="name">
  3.     Name: Xander
  4.   </p>
  5.   <p class="brain-weight">
  6.     Brain weight: 2.8
  7.   </p>
  8. </div>

Figure 3. Xander

But if $name was "Willow" and $brain_weight was 3.6, the output would be:

  1. <div class="customer">
  2.   <p class="name">
  3.     Name: Willow
  4.   </p>
  5.   <p class="brain-weight">
  6.     Brain weight: 3.6
  7.   </p>
  8. </div>

Figure 4. Willow

So a Drupal template is like a Mad Lib:

A Mad Lib

Figure 5. A Mad Lib

 

The PHP variables are the blanks in the Mad Lib. Use different words for the blanks in the Mad Lib, and you get a different story. Use different values for variables in a .tpl.php, and you get different HTML.

Remember that we want to follow raw data on its quest to become HTML. The last step is putting variables into templates:

Last step

Figure 6. Last step in the journey

Templates don't spit data at the user, not directly. Instead, each template puts its output into a variable:

Template output into variable

Figure 7. Template output into variable

 

Why? So that templates can work like...

Russian dolls

Russian dolls

Figure 8. Russian dolls

(Credit: backpackphotography)

Templates nest one inside the other, like the dolls. A template stores its output in a variable. Another template uses that variable inside itself.

Nested templates

Figure 9. Nested templates

Here's the customer template again, from Figure 2:

  1. <div class="customer">
  2.   <p class="name">
  3.     Name: <?php print $name; ?>
  4.   </p>
  5.   <p class="brain-weight">
  6.     Brain weight: <?php print $brain_weight; ?>
  7.   </p>
  8. </div>

Figure 2 (again). Customer template
customer.tpl.php

Here's a product template:

  1. <div class="product">
  2.   <p class="name">
  3.     Name: <?php print $name; ?>
  4.   </p>
  5.   <p class="price">
  6.     Price: $<?php print $price; ?>
  7.   </p>
  8. </div>

Figure 10. Product template
product.tpl.php

It uses the variable $name as well, but it means something different in the product template than in the customer template.

Here's the order template:

  1. <div class="order">
  2.   <div class="order-customer">
  3.     <?php print $customer; ?>
  4.   </div>
  5.   <div class="order-product">
  6.     <?php print $product; ?>
  7.   </div>
  8. </div>

Figure 11. Order template
order.tpl.php

The three templates work together. Here's some code-like stuff that uses the templates to create the final HTML. Drupal doesn't use this code; it's just to help you understand what's going on.

  1. //Apply the customer template.
  2. $name = 'Willow';
  3. $brain_weight = 3.8;
  4. $customer = apply_template('customer.tpl.php', $name, $brain_weight);
  5.  
  6. //Apply the product template.
  7. $name = 'Fenny snake';
  8. $price = 6;
  9. $product = apply_template('product.tpl.php', $name, $price);
  10.  
  11. //Apply the order template.
  12. $order = apply_template('order.tpl.php', $customer, $product);
  13.  
  14. //Show to the user.
  15. print $order;

Figure 12. Creating the final HTML

Here's the result:

  1. <div class="order">
  2.   <div class="order-customer">
  3.     <div class="customer">
  4.       <p class="name">
  5.         Name: Willow
  6.       </p>
  7.       <p class="brain-weight">
  8.         Brain weight: 3.6
  9.       </p>
  10.     </div>
  11.   </div>
  12.   <div class="order-product">
  13.     <div class="product">
  14.       <p class="name">
  15.         Name: Fenny snake
  16.       </p>
  17.       <p class="price">
  18.         Price: $6
  19.       </p>
  20.     </div>
  21.   </div>
  22. </div>

Figure 13. Final HTML

Why does Drupal do all that nesting? The first reason is flexibility. Suppose you want to add a warning when the customer is a known zombie. You can change customer.tpl.php:

  1. <div class="customer">
  2.   <p class="name">
  3.     Name: <?php print $name; ?>
  4.   </p>
  5.   <p class="brain-weight">
  6.     Brain weight: <?php print $brain_weight; ?>
  7.   </p>
  8.   <?php if ( $is_customer_zombie ) : ?>
  9.     <p class="zombie-warning">
  10.       Warning! This customer is a zombie!
  11.     </p>
  12.   <?php endif; ?>
  13. </div>

Figure 14. New customer template

You only change customer.tpl.php, and add the new variable to the template's processing. You don't need to change the other two templates.

Another reason is reuse. You can reuse customer.tpl.php for, say, email marketing reports. You can reuse product.tpl.php for an inventory report.

Daddy, where does the data in the variables come from?

Well, dear, Daddy data and Mommy data love each other very much. They have a special hug, and...

No, wait, bad metaphor.

Here's the Drupal-doesn't-use-it-but-does-something-similar code again:

  1. //Apply the customer template.
  2. $name = 'Willow';
  3. $brain_weight = 3.8;
  4. $customer = apply_template('customer.tpl.php', $name, $brain_weight);
  5.  
  6. //Apply the product template.
  7. $name = 'Fenny snake';
  8. $price = 6;
  9. $product = apply_template('product.tpl.php', $name, $price);
  10.  
  11. //Apply the order template.
  12. $order = apply_template('order.tpl.php', $customer, $product);
  13.  
  14. //Show to the user.
  15. print $order;

Figure 12 (again). Creating the final HTML

Line 12 uses the variable $customer to fill in the order.tpl.php template. Where does $customer get its value? From the output of another template (line 4). That's one place template variables get data: from other templates.

OK, but $customer is based on $name and $brain_weight. Where did they get their values? In Figure 12, we just typed them in. But in reality, Drupal looks up the values in the database. Some time in the past, a user typed data about Willow (the customer) into a form. Drupal stored that information in a database table. Maybe it created a row in a table called customer, with the data "Willow" and 3.8. When it comes time to create a report about Willow, Drupal looks that data up, and sets some variables. Here's some non-Drupal non-code:

  1. $row = find record where name = 'Willow';
  2. $brain_weight = get_field($row, 'brain_weight');

Where is this code kept? As part of a module, usually. So when you install the Zombie Sales module from http://drupal.org/project/zombie_sales, you add the code to your site.

So, variable values come from templates, and from data users have entered into the database.

The third place they come from is the administrator's configuration of the site. Here's part of a page you should recognize:

Site information

Figure 15. Site information

A template might use the data like this:

  1. <head>
  2.   <title>
  3.     <?php print $site_name; ?>
  4.   </title>
  5.   ...
  6. </head>

So templates put variables inside HTML. The variables get their values from:

  • The output of other templates.
  • Data entered by users.
  • Configuration by the site administrator.

That's all for now...

That's the end of part 1. Hopefully, you can avoid zombificating.

If there's a part 2, we'll look at some real Drupal template files.

Add a comment

Basic WYSIWYG

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <blockquote> <br> <cite> <code> <dd> <div> <dl> <dt> <em> <h2> <h3> <h4> <h5> <img> <li> <ol> <p> <pre> <span> <strong> <ul>
    Allowed Style properties: border, border-style, border-width, float, height, margin, margin-left, position, text-align, width

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Images
Images for your comment.
Files must be less than 1 MB.
Allowed file types: png gif jpg jpeg.
CAPTCHA
Prove that your are sentient. Code has letters only.
Image CAPTCHA
Enter the characters shown in the image.