How to add attach custom data fields to Drupal entities.

field.module template_preprocess_field(&$variables, $hook)

Theme preprocess function for theme_field() and field.tpl.php.

The function template_preprocess_field can be used to manipulate just the markup of the field in the $variables array before it’s output to your theme. There are a number of reasons why you would want to use this function as apposed to overriding field.tpl.php or node.tpl.php in your theme:

It’s faster. Processing an efficient php function will always be faster than Drupal’s template override system, looking for the right file and processing it.
Less Code. When you override the output of the node.tpl.php file to adjust a single field output you are also taking on the responsibility of outputting every field in the specific manner you want. So it could take a large amount of code to build a functioning node override.
Fewer files to manage. When overriding the field.tpl.php you’ll end up with a new file for every field you override (something like field–field-name.tpl.php).

Usage

In this example I’m going to take a geofield and change its output to provide a link to a Google Map. Geofield integrates well with OpenLayers, but in this case I don’t want the overhead of OpenLayers and don’t need to actually display the maps on the node.

First, create the template_preprocess_field function in the template.php file of your theme. Replace the word template with your theme name or you will end up with a WSOD.

function template_preprocess_field(&$vars) {
// Your code goes here.
}

The next step is to isolate the field that you would like to override. I do that with an if statement that tests for the the field name.

if($vars['element']['#field_name'] == ‘field_event_geofield’) {

}

Note: I’m using the $vars array (which is this functions name for $variables). A useful step at this point is to print this array inside the if statement. If you have the devel module turned on this can usually be done with dpm($vars);. However, in the template_preprocess_field function I had hit or miss success using dpm(). I’m not sure why it only works for certain fields, but kpr() works flawlessly. So I would recommend placing the line kpr($vars); inside this if statement so you can see the entire array.

The markup for your field will be located in the array at $vars['items']['0']['#markup']. This is what we want to override. In our example the markup for geofield will likely be something like “Latitude 29.419992, Longitude -98.484321” which is useless. We need the values for each part latitude and longitude to construct the url.

The raw values of the field are located in the $vars array at $vars['element']['#items']['0'][‘lat’] & $vars['element']['#items']['0'][‘lat’];

With this information we can rebuild the field markup. First I’m going to check that values exist for latitude and longitude, then create the link to google maps using those values. So this is how we put it all together.

function template_preprocess_field(&$vars) {
if($vars['element']['#field_name'] == ‘field_event_geofield’) {
//kpr($vars); //Uncomment to output the $vars array.
if(isset($vars['element']['#items']['0']['lat']) && isset($vars['element']['#items']['0']['lon'])) {
$vars['items']['0']['#markup'] = ‘View Map’;
}
return;
}
}

If you need to override multiple fields then repeat everything in the if($vars['element']['#field_name']) statement within the same template_preprocess_field function, and customize it. It’s also a good idea to add the line “return;” to the end of the if statement to increase the speed of the function by exiting as soon as possible.

As with many things in Drupal there are multiple ways to accomplish the same task. The template_preprocess_field function is my favorite, the fastest and I believe the simplest way to override the markup of a few select fields. If you have other ideas or suggestions or you find this helpful, please let us know in the comments.

Example:

Function templatename_preprocess_field(&$variables) {
if($variables['element']['#field_name'] == ‘the_field_name’) {
if($variables['items']['0']['#markup'] == ‘thedefaultvalue’) {
$variables['items']['0']['#markup'] = ”;
}
}
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

WordPress.com.

Up ↑

%d bloggers like this: