Drupal 7 Fields: Digging Deep into the Data for Themers
There are a number of ways to display and theme fields within the node context using Drupal 7. From a broad module perspective, this might include Panels, Display Suite, Field Collections, Semantic Fields, Fences or others. Though it used to be more common in the Drupal 6 days, custom node theming still has it's place with Drupal 7 depending on the use case. That is to say, the tried and true node--custom.tpl.php. For the sake of this article, it would be node--events.tpl.php representing a custom event content type.
Usual Ways
In this article, I'll show how to really dig into data associated with a field and for that I'll use a preprocess function in your theme's template.php for the logic and then a variable for presentation in a custom node template.
When we think of presenting fields, typically it's at face value. So if you have an image field, you normally think in terms of showing that image and in most cases either a default is fine or something more robust such as Display Suite for laying out your fields as they relate to each other. There are also image styles and more advanced imagecache type modules.
Method
But what if we want to render other data that's associated with a field? For this I'll use a Drupal API function called: field_get_items which returns an array of field items. The advantage of using this method is you do not need to specify language attributes as it's taken care of automatically. So essentially that means we don't need to use the infamous ['und'] or [LANGUAGE_NONE] which is a good thing.
Get the Array Elements of a Node Object
To get possible values for a field, I can simply do this in my custom node template:
print '<pre>';
var_dump(get_defined_vars());
print '</pre>';
The code above prints an array of values for any given field that's associated with the content type you are working with.
["field_event_image"]=>
array(1) {
[0]=>
array(14) {
["fid"]=>
string(2) "56"
["alt"]=>
string(54) "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
["title"]=>
string(54) "Integer nisi nunc, dictum in blandit id, euismod vitae dui"
["width"]=>
string(3) "500"
["height"]=>
string(3) "500"
["uid"]=>
string(1) "1"
["filename"]=>
string(0) ""
["uri"]=>
string(47) "public://event-images/./imagefield_sq1yqv_0.jpg"
["filemime"]=>
string(9) "image/jpg"
["filesize"]=>
string(5) "43123"
["status"]=>
string(1) "1"
["timestamp"]=>
string(10) "1348629689"
["origname"]=>
string(0) ""
["rdf_mapping"]=>
array(0) {
}
}
}
Write the Preprocess Function to Define Variables
Offhand, this does not seem really useful but in reality, it's like a goldmine for themers. We can take an element and display it with a variable created with a preprocess function. For example, let's display the filetype of the image that was uploaded. In this case it's 'filemime'. In your theme's template.PHP, create a preoprocess function for node.
function MYTHEME_preprocess_node(&$vars, $hook) { //… code will go here
}
First, we define node:
$node = $vars['node'];
Then we define a variable for the field entity using field get items.
$event_image_items = field_get_items('node', $node, 'field_event_image');
The name of our field is field_event_image and we define a variable to use called $event_image_items. Now we can define individual variables for any element of the field.
$vars['mimetype'] = $event_image_items[0]['filemime'];
I made up a variable here called 'mimetype' that will grab the value for the 'filemime' element of the field. Here is the complete preprocess function.
function MYTHEME_preprocess_node(&$vars, $hook) {
// Globals.
$node = $vars['node'];
// Load data from 'field_event_image'.
$event_image_items = field_get_items('node', $node, 'field_event_image');
// Load individual data from 'field_event_image'.
$vars['mimetype'] = $event_image_items[0]['filemime'];
}
Render the Variable and Theme Away!
Now simply render the variable in node--events.tpl.php (which is the custom node template for my custom content type "events" in my theme folder.
<?php print $mimetype; ?>
As always, keep calm and clear cache and voila, we get image/jpg printed out on the page! Now you are free to theme this however you want with wrapped HTML, classes and corresponding CSS. The nice thing about this is your node code is simple and elegant and not crowded with logic, that's all in template.php. This method opens up tremendous opportunities for theming.
In my next post, I'll expand upon this concept and show how to leverage other parts of Drupal's api to expand and format field data such as time, filesize and image styles.
Resources