Last weekend we held our first hands on Drupal Theming and Site Building workshop. The workshop was a success in helping the participants fully visualize the process that is known as Drupal theming. Many contributed modules were covered like Views, Panels, CCK, Emfield and more. Special attention was given to the properly using template file overrides and working with the template.php file from the Zen theme.
Today I am posting some of the notes and code snippets that were used during instruction and demonstration for all to enjoy.
Basic Theme Variable Debugging
At the start of class we covered some basic PHP syntax and use and covered a few basic print functions that allow a themer to inspect which variables are available for outputting to the screen.
print_r
The following function is used very frequently to dump the contents of a variable (whether its type is boolean, string, integer, array, or object). Notice that passing a value of TRUE to the second parameter tells the function to return the contents instead of print to screen.
<?php
print_r($variable);
print '<pre>'. print_r($variable, TRUE) .'</pre>';
?>PHP documentation for print_r()
Date and Time
We also discussed the use of PHPs date function and token replacement syntax. For full documentation as well as examples of how this works I recommend reading the php documentation for date().
Heredoc Syntax
Used in situations where providing a template file doesn't suffix, PHP coders can use heredoc syntax to more easily type html and php tags together into a string (or in the case of Drupal, an output variable that gets returned back to the theme system).
PHP documentation for strings and heredoc syntax
Important Drupal Functions & API
In addition to the core PHP functions that are used throughout Drupal code, there are additional functions that the Drupal Core defines. These functions are referred to as being a part of the Drupal API (application programming interface). Lucky for us Drupalers, we have a great API website that has good documentation and a great search feature that helps us find functions by autocompleting our search text.
A list of the most basic and often seen functions by themers is below:
Template Structure
Because there is so much to talk about with the template structure, I highly recommend just visiting the Drupal handbook pages. The handbooks do a great job of presenting the principles and demo source code.
Drupal 5 Theming Handbook
Drupal 6 Theming Handbook
CSS and JS
We also introduced two important functions for adding css and js files at different places in your code (and thus different places on your site). Separating css files can be a great thing when styles are specific to only a single node type, or a certain view. However, it can be difficult to manage if you are replicating css in multiple files across your site so we recommend that you be thoughtful of this when using this technique.
It is also important to note that using this technique provides for a clean way to move template files around from site to site because sometimes the location of a particular theme may change from one installation to the next, using this method drupal will tell you where the theme folder is located and thus hard coded links are avoided.
<?php
drupal_add_css(drupal_get_path('theme', '[YOUR THEME NAME HERE]') .'/[PATH TO YOUR STYLESHEET INSIDE YOUR THEME DIRECTORY]', 'theme');
?>For example the following code will load the css file view-name.css located within the css folder inside of your zen theme folder. In a typical installation the path would look as follows.
sites/all/themes/zen/css/view-name.css
<?php
drupal_add_css(drupal_get_path('theme', 'zen') .'/css/view-name.css', 'theme');
?>Adding a javascript file is very similar and can be done with the drupal_add_js function. The following snippet will add a js file located at: sites/all/themes/zen/js/view-js.js.
<?php
drupal_add_js(drupal_get_path('theme', 'zen') .'/js/view-js.js', 'theme');
?>Views Overrides
In the class we covered how a theme override worked by inserting the proper functions in the template.php file. We went on to show concrete examples of this by using the drupal 6 devel module which showed exactly which function created each snippet of code and which suggested function names/template files could be used to override it. We then showed how the views theming wizard can be used to generate the proper functions for overriding the views it produces.
Views theming documentation
Devel Module Project Page
Great screencast walking through how to override the table view type for views
After showing how to override each view we dove in further and showed how the theme wizard will show you which individual fields could be themed along with suggested function names and a base function body to copy and paste into the template.php file.
Panels Information (Panels 2)
We also briefly introduced the panels module and worked on creating a new homepage using panels and then pulling in data from views to create lists of recent content. Late in the class we had the opportunity to also run through some code snippets and tricks for the panels module. One of the important concepts we discussed was the difference between displays, regions, and panes.
- The display is considered to be just like the page of the panel.
- The display includes all of the 'regions' within the panel. Each of the regions in the pane is similar to a region in the page.tpl.php file (i.e. Left Sidebar, Right Sidebar, Content Top, etc).
- Lastly panes are similar and often refrered to as 'blocks'. Panes are the individual blocks of content that are inserted one at a time into the panels regions.
Just like the views module, the panels module has a theming function that gets called whenever a display is loaded (configured in the panels/layout/[layoutfile.inc], as shown at the end of class), as well as a theme function that gets called to theme each individual pane that is loaded into the display.
During class we did a walk through to demonstrate how by reading the panels layouts includes one could easily create a custom module that defines a custom panel layout. One of the advantages to doing this are so that changes to a custom width/height row/column combination layout can be easily updated with the change of a single file, as opposed to updating the layout settings for each individual node.
Along with additional panels resources from the LADrupal February Meetup, I have attached a module download which can be easily used/adapted to create a custom panel layout. http://boldsource.com/articles/ladrupal-panels-presentation-notes
Automatic pane template file override
Also shown during the panels presentation was sample code that can be inserted into your template.php file that makes it so everytime a panel pane is loaded, it searches for an appropriately named pane-[panetype]-[pane-sub-type].tpl.php file.
/**
* Render a panel pane like a block.
*
* A panel pane can have the following fields:
*
* $pane->type -- the content type inside this pane
* $pane->subtype -- The subtype, if applicable. If a view it will be the
* view name; if a node it will be the nid, etc.
* $content->title -- The title of the content
* $content->content -- The actual content
* $content->links -- Any links associated with the content
* $content->more -- An optional 'more' link (destination only)
* $content->admin_links -- Administrative links associated with the content
* $content->feeds -- Any feed icons or associated with the content
* $content->subject -- A legacy setting for block compatibility
* $content->module -- A legacy setting for block compatibility
* $content->delta -- A legacy setting for block compatibility
*/
function phptemplate_panels_pane($content, $pane, $display) {
// catch the pane type and send it off to a custom tpl file
$hook = 'pane';
$suggestions[] = $hook;
$suggestions[] = $hook .'-'. $pane->type;
$suggestions[] = $hook .'-'. $pane->type .'-'. $pane->subtype;
return _phptemplate_callback($hook, array('content' => $content, 'pane' => $pane, 'display' => $display), $suggestions);
}
?>
Remember that based on our demonstration of how to use the _phptemplate_callback function, you will have 2 variables available within the pane-....tpl.php file: $content, and $pane. I would suggest using print_r($content) or print_r($pane) as a means to determine what data is available to print.
Thanks!
I want to end by saying thank you to those people who registered and attended the class. We all worked very hard for the 14 hours of class time to get through as much material as possible while keeping the instruction meaningful and applicable to sites you all were working on.
Additions & Comments
Please feel free to add comments or ask questions about the material presented above, I will do my best to answer them in a timely manner. I posted it so that it will help people learn! Feel free to link to this documentation on your own sites, groups.drupal.org, the drupal forum, or any other site for that matter.







I also wanted to add that
I also wanted to add that Pakt Publishing has two great books out for beginners, one is more oriented towards building out websites with basic modules and the other focused on helping a themer understand what, where and how Drupal can be themed. They can both be found here: http://www.packtpub.com/drupal-books.
Drupal 5 Themes
Building Powerful and Robust Websites with Drupal 6
Nice article and
Nice article and overview.
Idea:
instead of using
print '<pre>'. print_r($variable, TRUE) .'</pre>';maybe it could be more practical to create (temporary?) function in your
template.php file
function _MY_TEMPLATE_print_r ($var) {print '<pre>'. print_r($var, TRUE) .'</pre>';
}
and to invoke it in your tpl.php files
_MY_TEMPLATE_print_r ($variable);Nice summary. A lot of these
Nice summary. A lot of these things are very subjective, though. I personally don't think the convenience of heredoc syntax outweighs the downside of less comprehensible code due to spoiling your indenting.
When prettyprinting, I like to throw the htmlentities() function in there as well, to catch any markup that might be contained in the variable:
<pre><?php print htmlentities(print_r($var,1)) ?></pre>...and using drupal_set_message() rather than print() means you can safely debug from places other than template files:
drupal_set_message('<pre>'.htmlentities(print_r($var,1)).'</pre>');And you can't talk about check_plain() without mentioning check_markup() as well.
wonderful article everything
wonderful article everything is tackled here
love your post its very
love your post its very informative.
thanks for the tutorial.
thanks for the tutorial.
All the treasures of the
All the treasures of the earth would not bring back one lost moment. ?????
good
good
Post new comment