Theming Views In Drupal 6.x

Who remembers good ol' Views 1.x in Drupal 5.x? Lovely, wasn't it? With that theming wizard. Giving you all the phptemplate functions you needed for fine-grained theming, ready to paste in to template.php in your theme and fiddle with until everything looks perfect.

Well, that was then. Many of you, like me, may have been looking at the latest version, 6.x-2.0, and scratching your heads when it comes to theming. Sure, the new Views UI is fantastic. And for basic (or non-developer) theming the new view tpl files are a great idea. In fact, theming with Views templates is not even basic. You can do nearly anything.

HOWEVER...

...for very complex theming tasks the chances are you'll need to create a tpl file for your view and *every* *field*. The system is fantastic if you want to maybe theme the overall view and a couple of fields, and most people will never need anything else, but any more than that in terms of theming requirements and it starts to become unweildy. Still perfectly workable, but unweildy nevertheless. I'm working on a project at the moment which makes me yearn for the old ways. I have dozens of views, each one needing fine-tuned bespoke theming, which means dozens and dozens of tpl files, potentially.

I really didn't like the idea of that, even though you can apparently order tpl files in sub-folders in Drupal 6.x without there being any performance overhead (caching cleverness there). So I started picking the Views code apart for an alternative, largely because I stubbornly refused to believe the Views developers would have removed such a handy way of theming and replaced it with nothing. And they haven't. But they won't talk about it (and with good reason - read on).

The first thing of interest I discovered was a function called _views_theme_functions() in the theme.inc file that ships with Views 2.x. This function appeared to provide a bunch of dynamically generated theme functions which can be over-ridden in template.php. Armed with that possibility, my colleague Graham started searching the Internet for a solution, and came up with this:
http://www.agileapproach.com/blog-entry/theming-views-drupal-6

It's not wholly accurate (see my post here) but it's a great starting point. In fact, I pitched in a feature request asking for it to be added to the documentation.

Which is when the Views maintainer, 'merlinofchaos', jumped in and said "No!" - firmly, but politely. He makes several valid points and suggestions in afforementioned feature request which are well worth reading, and guided me in the direction of better understanding the Drupal 6.x theming system before hacking too far in to the Views module.

Enter preprocess functions. While that page explains them to a degree, it rather implies that modules and/or themes effectively create the environment for tpl files to exist. This is true to an extent, but a tpl file does not have to have a preprocess function shadowing it. A subtlety I had missed until now.

The Views module is an excellent example of this. There are several preprocess functions within the Views module which are generic but have specific purposes. One is called template_preprocess_views_view() and it is responsible for generating *all* view tpl files with filename in the form views-view--my-view-name.tpl.php. Another, template_preprocess_views_view_list(), acts upon all variations of views-view-list--my-view-name.tpl.php, etc. You get the idea.

All possible variations of valid view template file names are demonstrated here, each set of variations having its own default preprocess function provided by the Views module:
http://views.doc.logrus.com/group__views__templates.html

Usually, given the documentation about preprocess functions, a tpl file with a name in the form of views-view--my-view-name.tpl.php would mean you might expect to find, in a module somewhere, a preprocess function called template_preprocess_views_view__my_view_name(), but with Views you won't find one, because the function handling that tpl file is the generic one, template_preprocess_views_view().

So if there's no default preprocess function to add variables to, that means you can't add variables via a preprocess hook in your theme, right?

Wrong! You can still define a preprocess function in template.php which can still add variables to a view tpl file, because it is the tpl file that must exist for this to work, not the default preprocess function. (Note, work is underway to make neither an absolute requirement.) If there is a tpl file, there can be a preprocess function (hook) to add variables to it in your theme, even if the module initially facilitating the tpl file does not have such a default function.

So with that in mind, first I need to create my tpl file. If I have a view called 'my_view' then I need to create a tpl file in my theme called views-view--my-view.tpl.php (you can get the list of valid tpl names for any view from the Views UI and you would copy the appropriate stub template from the 'theme' directory in the Views module installation directory).

Now my tpl file exists, if we are using the Garland theme I can put this in template.php:

<?php
function garland_preprocess_views_view__my_view(&$variables) {
 
$variables['foo'] = 'some text';
}
?>

And in the tpl file I now have a $foo variable available, as you would expect having read the preprocess function page. So in the tpl file you can do this:

<?php
if ($foo) {
  print
$foo;
}
?>

Now in $variables *all* your view data is available, so with your preprocess function you can expose anything you like as a variable. You could also load additional stuff and pass it in, but I'm sure I can leave you to work all that out.

In short: a combination of tpl files and preprocess functions effectively replace phptemplate theme override functions for Views, allowing you to pass any additional variables you might need to the basic view template for any view, meaning I can customise the available variables within template.php and make sure I only need one tpl file for each view, which suits my purposes perfectly. And this is much better than the old system, because there is now a true separation of data from mark-up, where template.php becomes pure logic, passing variables to be placed in the mark-up provided by the tpl files.

You can see my original thread with 'merlinofchaos' here, and he makes a good point about symlinks in Linux there as well as other theming tips too, so also well worth a read. Ignore my 'preprocessor' typo. =)

11 comments

by Anonymous on Sat, 06/06/2009 - 13:28

They are wonderful. And they’re even more wonderful in D6. I suppose they weren’t around in D5, but there was the theming wizard, which sorta was like having templates, just not as useful. But what do I love even more than the tpl files???? The CSS classes. Yes I said it, the classes! All of them! Every last stinking one. Why? Because they help you layer in design logic, a very important technique for theming.

by Anonymous on Thu, 11/06/2009 - 17:04

I can customise the available variables within template.php and make sure I only need one tpl file for each view, which suits my purposes perfectly.
wow this is the best part customization is what i alwyas wanted in this tool.

by Tim Hadler on Wed, 17/06/2009 - 15:19

After reading your post I'm a little bit more confident about the different themes that I can adapt and changes on one of my blogs. It looks as though it isn't that complicated, even though I do tell myself it is harder than it actually is all the time. Still tryin to get my head fully around css classes and how they work with blogs but so far looks to be good.

by ussher on Thu, 10/09/2009 - 02:16

Thanks so much for this.

Your information has been a real catalyst for getting going theming views.

Awesome.

by Alex on Wed, 18/11/2009 - 17:12

Thanks - great for adding jquery to views

by Anonymous on Wed, 30/06/2010 - 10:41

Hi, i jus started using D6 so i am not very clear on how it works.
Will it be possible if someone can teach me how to display some of the variables?

for example some cck fields.

thanks

by Tak on Wed, 28/07/2010 - 14:47

This is the best description of theme a view so far I found on the web. Others seems to always missing one or two points. Thanks. This is very useful

by Andrew on Wed, 05/01/2011 - 19:33

This is a great article with some great links thank you. I am looking for references to print $content as this seem to pull the attached image into the content along with a link and it's aligned right. Tracking where it originates and how to theme better is quite a challenge, so any replies would be great. Thank you Andrew

by pjsz on Mon, 13/06/2011 - 14:09

Ahhh , i feel your pain. That would be a quest i would like to undertake too .You think , "Oh, i can theme that node or view -- just copy x.tpl.php and put your own markup around the variables." Only to find there is one variable - $content.

Drupal seems to like you to theme each individual variable one at a time , rather than a whole page of variables all at the same time. Just look at the views templates -- you have one for the whole view, one for the table or display type, one for all the fields and one for each individual field. It's not real easy to track . Its more of a bottom up process rather than top down.

Coming from an mvc framework background where I would create my $variables and pass them to the template page and that template page would include other sub templates and pass them the $variables for each section of the page. It was much easier to trace the code just by looking at a template. But there wasn't the magic and modular features of drupal.

This article has been so helpful. Well written to explain and provide the much needed example :) Now i'm at a point where i have to decide to use drupal or an mvc framework for a rewrite of a customized curriculum management system. IMO a curriculum management system is almost all CMS. I mean the the acronymns are even the same. Thanks for this article filled a critical gap in my theming ability.

by Robert Archer on Tue, 27/09/2011 - 19:13

Very awesome article here. I have my preprocess functions being accessed as they are supposed to be. But, what I'm trying to do is add a field to the fields template by adding to $variables['view']->result or $variables['view']['rendered_fields'][$key]['nc']. They seem to get added fine, but don't show up in my custom fields template in the $row variable.

Code is here:

function cpe_preprocess_views_view__course_subjects__page(&$variables) {
  // go through the results and get the information for each field.
  foreach($variables['view']->result AS $key => &$result) {
     $empty_count = db_result(db_query("SELECT COUNT(*)
     FROM {term_data}
     LEFT JOIN {term_node} ON {term_data}.tid = {term_node}.tid
     INNER JOIN {node} ON {term_node}.vid = {node}.vid
     LEFT JOIN {content_field_credits} ON {node}.vid = {content_field_credits}.vid
     WHERE content_field_credits.field_credits_value <> 0 AND {term_node}.tid = $result->tid"));
     $result->nc = ($empty_count == 0);
     $variables['view']['rendered_fields'][$key]['nc'] = ($empty_count == 0);
  }
}

thanks for any help.

by Diwant Vaidya on Wed, 28/09/2011 - 21:03

Thanks, this was very helpful in theming views.

Post new comment

© 2010 Greg Harvey. Drupal theme by Kiwi Themes.