[development] .tpl-ifying Drupal

Earl Miles merlin at logrus.com
Fri May 4 00:05:33 UTC 2007

Robin Monks wrote:
> Hey,
>   From someone who hasn't really been following the changes, but who 
> really hates PHPTemplate (which is designed more toward developers, 
> rather than graphics artists and end users IMHO) and would much rather 
> use Smarty... Will Smarty still be available as an option in 6?  AKA. 
> Will theme engines support still be there?
> Robin

In fact, I believe that smarty will be better (assuming someone maintains it 
and ports it to Drupal 6) due to these changes.

The actual code in phptemplate.engine has been vastly reduced, and much of what 
it does has been made inherent to Drupal, and it the PHPTemplate renderer has 
been made the default renderer. Theme engines tell Drupal to use a different 
renderer (and, if they like a different extension).

Additionally, theming with templates has been broken up into two sections, one 
for pre-processing, which is designed to transform data into something more 
suited for presentation (i.e, business logic), leaving the actual presenting to 
the template (presentation code).

If you're familiar with the _phptemplate_variables() function in PHPTemplate, 
what we've done is made it so that *every* theme template gets one (actually, a 
series) of these in order to massage the variables so that the template itself 
can do as little as possible. Let's take a fairly minor example:

Grabbing a theme function from aggregator module:

function theme_aggregator_feed($feed) {
   $output  = '<div class="feed-source">';
   $output .= theme('feed_icon', $feed->url) ."\n";
   $output .= $feed->image;
   $output .= '<div class="feed-description">'. 
aggregator_filter_xss($feed->description) ."</div>\n";
   $output .= '<div class="feed-url"><em>'. t('URL:') .'</em> '. l($feed->link, 
$feed->link, array('absolute' => TRUE)) ."</div>\n";

   if ($feed->checked) {
     $updated = t('@time ago', array('@time' => format_interval(time() - 
   else {
     $updated = t('never');

   if (user_access('administer news feeds')) {
     $updated = l($updated, 'admin/content/aggregator');

   $output .= '<div class="feed-updated"><em>'. t('Updated:') . "</em> 
   $output .= "</div>\n";

   return $output;

That's not terribly bad on its own, but it has a couple of things we really 
don't like to see at the theme layer, particularly that filter_xss, which is a 
real bear when using an alternate theme. The way this will look in Drupal 6 
will be, approximately:

  * All arguments sent to the theme template will be in $variables. The only
  * argument this template accepts is 'feed', so we'll look there.

function template_preprocess_aggregator_feed(&$variables) {
   $feed = $variables['feed'];
   $variables['feed_icon'] = theme('feed_icon', $feed->url);
   $variables['feed_image'] = $feed->image;
   $variables['description'] = aggregator_filter_xss($feed->description);
   $variables['feed_url'] = l($feed->link, $feed->link, array('absolute' => TRUE));
   if ($feed->checked) {
     $variables['updated'] = t('@time ago', array('@time' => 
format_interval(time() - $feed->checked)));
   else {
     $variables['updated'] = t('Never');

   if (user_access('administer news feeds')) {
     $variables['updated'] = l($updated, 'admin/content/aggregator');

And then, aggregator_feed.tpl.php will look like this:

<div class="feed-source">
<?php print $feed_url ?>
<?php print $feed_image ?>
<div class="feed-description">
   <?php print $description ?>
<div class="feed-url">
   <em><?php print t('URL:') ?></em> <?php print $feed_url ?>
<div class="feed-updated">
   <?php print t('Updated:') ?></em> <?php print $updated ?>

As you can see, this template can be in almost any language, with the exception 
that it probably should somehow support t(). However, it doesn't have to, 
because we have preserved and improved the old _phptemplate_variables() 
functionality. You can create this function:

phptemplate_preprocess_aggregator_feed(&$variables) {


phptemplate_engine_preprocess_aggregator_feed(&$variables) {


garland_preprocess_aggregator_feed(&$variables) {

Note that the engine gets its very own preprocess function if it needs it. This 
isn't used by PHPTemplate at all, at this point, but other templating engines 
may need it to do auto-transformation should they so desire.


More information about the development mailing list