Setting up variables for use in a template (preprocess functions)

Preprocess functions only apply to theming hooks implemented as templates. The main role of the preprocessor is to setup variables to be placed within the template (.tpl.php) files. Plain theme functions do not interact with preprocessors.

Notes:

  • In order for your theme to have its preprocessors recognized, the template associated with the hook must exist inside the theme. Beginning with Drupal 6.7, this is no longer necessary. When a default template exists, copy it to your theme and clear the registry. If you are converting a theme function into a template, read the parent page on getting the hook to register as a template.
  • Preprocessors are also used for providing template suggestions.
  • In versions 5 and below, the function _phptemplate_variables served the same purpose. It has been deprecated in 6.

There can be numerous preprocessors for each theming hook. Every layer from core, modules, engines and themes can have one, each progressively building upon the variables before being rendered through template files. This keeps the markup clean and easy to work with inside templates by placing most of the logic inside these preprocessors.

Here are the expected preprocessors. They are run in this order when they exist:

  1. template_preprocess
    - This is supplied by core and always added. The variables generated here are used for every templated hook.
  2. template_preprocess_hook
    - The module or core file that implements the theming hook supplies this. The initial generation of all the variables specific to the hook is usually done here.
  3. moduleName_preprocess
    - Do not confuse this with the preprocessor before it. This allows modules that did not originally implement the hook to influence the variables. Applies to all hooks.
  4. moduleName_preprocess_hook
    - Same idea as the previous preprocessor but for specific hooks.
  5. engineName_engine_preprocess
    - The preprocessor for theming engines. Applies to all hooks.
  6. engineName_engine_preprocess_hook
    - Another preprocessor for theming engines but specific to a single hook.
  7. engineName_preprocess
    - NOT RECOMMENDED. This is the first preprocessor that can be used inside the theme. It can be named after the theme engine the theme is running under. Applies to all hooks.
  8. engineName_preprocess_hook
    - NOT RECOMMENDED. Another preprocessor named after the engine but specific to a single hook.
  9. themeName_preprocess
    - This one is named after the theme itself. Applies to all hooks.
  10. themeName_preprocess_hook
    - Same as the previous preprocessor but for a specific hook.

There are many possibilities here for modifying the variables. In most cases, it is only the first two preprocessors that exists. The first, adding the default baseline variables and the second, adding a set specific to the theming hook. Contributed modules taking advantage of the preprocessor slots (3 & 4) should document their behavior. It will not be covered extensively here.

While it is possible, the default PHPTemplate does not inject itself to this list. (5 & 6)

Themes can start adding their preprocessors seventh in the list. The preprocess function should be added to the theme's template.php file. However, due to the problems listed below, it is recommended that themes use their own names as the prefix (9 & 10). It is possible to grow this list beyond the ten shown above by having sub-themes add preprocessors strictly through their theme name as it is shown in the last two examples.

A few notes:

  • There is an unfortunate design flaw/bug in the theme system when a theme is part of a base theme/sub-theme hierarchy. Any preprocess functions prefixed with engineName_preprocess will be run multiple times (once for each theme in the hierarchy) instead of just once. Not only is this wasting resources, it can also cause difficult-to-debug errors.
  • The theme name (9 & 10) should always be used for themes. This minimizes any chance of a sub-theme redeclaring a function with a engineName_preprocess prefix and causing fatal PHP errors due to duplicate functions.

Note that nothing should be returned from these functions and the variables have to be passed by reference indicated by the ampersand before variables, e.g., &$variables.

Since the variables set early on are run through all the latter preprocessors due to references, be careful that you do not inadvertently reset any added before your theme. It is fine to reset them but doing so accidentally can keep you guessing on what went wrong.

Example set from a module implementing the hook of "foo":

<?php
function template_preprocess_foo(&$variables) {
 
$variables['foo_list'] = array(
   
'list item 1',
   
'list item 2',
   
'list item 3',
  );
}
?>

And the preprocessor created from the theme to add to the variable set above:

<?php
function drop_preprocess_foo(&$variables) {
 
// Do not do this unless you mean to:
 
$variables['foo_list'] = array('list item 4');
 
 
// Instead do this:
 
$variables['foo_list'][] = 'list item 4';
}
?>

The variables that end up in the template file are the keys set within $variables. So, with the above example, the variable in the template would result in $foo_list.

When using a preprocessor not specific to a theming hook, a second parameter can be used which always passes the current hook. Using a more specialized preprocess function like the one shown above is easier to maintain but if there will be shared code for multiple theming hooks, you may want to opt for this instead.

<?php
function drop_preprocess(&$variables, $hook) {

 
// Shared between the 'foo' and 'bar' theming hooks.
 
if ($hook == 'foo' || $hook == 'bar') {
   
$variables['foobar_item'] = 'foobar item';
  }

 
// Specific to 'foo'.
 
if ($hook == 'foo') {
   
$variables['foo_item'] = 'foo item';
  }
 
// Specific to 'bar'.
 
elseif ($hook == 'bar') {
   
$variables['bar_items'] = 'bar item';
  }
}
?>

Related HowTo's and code snippets:

Can I add a simple "core indipendent" variable to a theme?

Dret - February 20, 2010 - 09:37

A very simple, stupid question:
I'm reading all the documentation on preprocessor, override theme, and so on...

But i can't find a way to add simply variables (not overriding the existing ones) in a theme using the template.php file .

A stupid example: I want to add a simple snippet to my page.tpl.php file link this: <?php print $hello >

The values of $hello are taken from a function in my tempalte.php file: for example $hello = 'Hi', if I'm on front page or $hello = 'goodmorning' in all other pages.

What the correct drupal way to make this!
Thanks!
Bye.

I think what you want to do

xenophyle - February 22, 2010 - 21:01

I think what you want to do in your preprocessor function is have a line to set that variable name as a key in the variable array:

function yourtheme_preprocess (&$vars, $hook) {
    $vars['hello'] = "hello world";
}

and that will result in a new variable $hello in your tpl.php.

Is that what you were looking for?

Yes, but I explain better

Dret - February 23, 2010 - 09:32

Yes, but I explain better my goal.

My final target is to move some functions from "page.tpl" to "template.php" page, for separating the presentation code from functional one and keep a clean markup.

This function in template.php should give, as final result, a snippet like:

<?php
$name_of_variable
?>

This is an example of a function that I would like to move from page.tpl to tempalte.tpl

<?php if (module_exists('path')) {
 
$alias = drupal_get_path_alias($_GET['q']);
 
$class = explode('/', $alias); $class_last = count($class)-2; }
  if (
$class_last >= 0 && $class[$class_last] == 'custom_name') {
  print (
'Custom_text: ') ;} ?>

Is a correct approach...? Can You make me an example?

Thanks a lot!
Bye

I'm not sure that I

xenophyle - February 23, 2010 - 22:05

I'm not sure that I understand your question, but if you post it in the Theming Forum (http://drupal.org/forum/3) more people will see your posting.

Move your code from tpl to template.php

patacra - March 23, 2010 - 07:59

As you're moving code from the page template, you'll have to add the hook_preprocess_page() to your template.php file :

<?php
/**
* Implementation of hook_preprocess_page()
*/
function yourtheme_preprocess_page(&$vars) {
 
$my_custom_variable = ''; // Default value.
 
 
if (module_exists('path')) {
   
$alias = drupal_get_path_alias($_GET['q']);
   
$class = explode('/', $alias);
   
$class_last = count($class) - 2;
  }
  if (
$class_last >= 0 && $class[$class_last] == 'custom_name') {
   
$my_custom_variable = 'Custom_text: ';
  }

 
// To add a custom variable to the page.tpl.php file just
  // create a new entry in the $vars array :
 
$vars['my_custom_variable'] = $my_custom_variable;
}
?>

In the page.tpl.php file, juste print your custom variable :

<?php
print $my_custom_variable;
?>

Et voilà!

By the way, I didn't try to understand what your code is doing, but it seems that you could use the Drupal's arg() function for your needs.

Patrick Janser

When are they run

joel box - Mond... - March 14, 2010 - 10:34

Hi when doing module development, the code changes during the process.
Is the new preprocess code detected after clearing cache, reinstall or on a regular refresh?

Cache

patacra - March 23, 2010 - 08:07

Hi,

If you just added a new hook_preprocess... to your module, Drupal will not have it registered, so it will not be called. You'll have to clear Drupal's cache to get it working.

But if the function is already present, but you are adding some code in it, then Drupal already knows it, so you don't need to clear Drupal's cache.

If you're doing a preprocess hook in your theme, you can avoid clearing all the cache. You can just clear the theme's cache instead. If you are using "Administration menu", you'll find the clear cache links on the first menu entry (the one with the favicon).

I hope I answered to your question.

Patrick Janser

thx Patrick, that's very

joel box - Mond... - March 25, 2010 - 22:18

thx Patrick, that's very clear.

 
 

Drupal is a registered trademark of Dries Buytaert.