Web Design

Advanced field templates

I recently had to adjust the output from a field on a page.  Here's how I did it.

There are some excellent articles and even instructional videos on how to override templates for things in Drupal - pages, content types, even individual fields.  But everything I found described how to alter the html wrapper around the field item, and said nothing about how to alter the field output itself.

The Challenge

For example: Let's say I've got some geolocation data.  I have stored latitude and longitude and the field is set to output as a geofield map.  But let's say I want to take that data and output it as a static map instead.

There's A Module For That

Of course there is.  You could use the geofield with staticmap modules.  But those are both community-contributed modules with few recent updates and little third-party support.  I found several patches that hadn't even been reviewed & tested by the community.  Naturally, the modules didn't work for me.

Note: I deeply appreciate the efforts of other community developers.  I'm a contrib module author myself and I respect how much effort it takes to publish a module, nonetheless support it.  Many modules are reliant on client funding.  In addition, if the community refuses to review a patch, the module maintainer can hardly be blamed for that.  All I'm saying is that these appear to be fringe cases that don't get the necessary support from the community as a whole.

Roll Up Your Sleeves

Time to roll a custom template.  This will probably go in your theme directory.  (One exception would be if you have a custom module and want to use it to modify the output of a field.)

Template files follow a naming convention.  For a field, it's "field--your_field_here.tpl.php."  In my case, it was field--field_location_computed.tpl.php.  Notes:

  • There are two dashes after "field" and before your field name.
  • Your field name is the machine name for your field.  See Admin > Structure > Content Types.

There's a lovely default that already exists for field templates.  Here it is:

<?php foreach ($items as $delta => $item) : ?>
  <?php print render($item); ?>
<?php endforeach; ?>

That's great, but the problem here is the render() function.  That's exactly what we don't want: pre-processed output from the field.  We want to reach inside the field, pull out the raw data inside, and serve it up with seaweed and rice.  Here's how:

$nid = arg(1); // Grab the node id from the url
$node = node_load($nid); // Load the node you want
$geo = field_get_items('node', $node, 'your_field_here'); // Load the field from the node

The field will be loaded as an array with all its bits and pieces inside.  You can use a print_r() to figure out what's in there and how to grab it.  Here's what it really looks like:

$nid = arg(1); // Grab the node id from the url
$node = node_load($nid); // Load the node you want
$geo = field_get_items('node', $node, 'field_location_computed'); // Load the field from the node
$lat = $geo[0]['lat'];
$lon = $geo[0]['lon'];
print '<div class="static"><img src="http://ojw.dev.openstreetmap.org/StaticMap/?show=1&layer=mapnik&z=17&size=500x500&mlat0=' . $lat . '&mlon0=' . $lon . '&lat=' . $lat . '&lon=' . $lon . '" /></div>';

This example code will print a static map image using data from the field:
 
You could, of course, write your own module with preprocess_ functions, or do something with views, blocks, and the viewfield module.  But why bother?  You can theme your output using a theme template file, which seems more appropriate somehow.  Using this technique, you can re-render any field and output the data any way you want, using html and php.  Pretty powerful for theme output.