Drupal logo

On Using Drupal 7 Fields & PHP Templates

Complete
Written by Siraj Sabihuddin
(Created on July 15, 2012 - 5:19pm)

I've spent hours trawling the web for information on doing things with Drupal 7. Most recently searching for a way to access a custom field programmatically. Essentially, adding content to Drupal 7 is controlled by creating a custom content type. We can add customizable data to this content type by creating fields, such as, text fields, radio buttons, image fields, etc. Creating these fields requires that the core Field Module and the contributed Field UI module be installed. Now, while these fields can be created using Drupal's web admin. interface. How exactly do you programmatically access the data stored in these fields? Well ... let's take a look.

Let's start by looking at the Drupal admin. interface, accessible via any web browser.  If you're using the default admin. theme (i.e. Bartik) then your interface should look as shown in figure 1. Let's suppose that the Fields Module is installed and that we want to create a custom content type called Snippet.

<strong>Figure 1:</strong> An example of the drupal admin. screen.<strong>Figure 2:</strong> The content types screen.

Creating a Content Type and Field

To create this custom content type, navigate to Administration > Structure > Content Type and click on Add Content Type.  See figure 2.  After filling in the required name field, we note that we now have an extra content type called Snippet (figure 3).  

<strong>Figure 3:</strong> An extra content type called Snippet is visible in the Content Type section.

In the content type section, clicking on the Manage Fields link allows us to add additional fields.  Lets add a field with label=NewField, with the name=field_newfield, field=Long Text type and Widget=Text Area and save.  See figure 4. This will create a new field for our Snippet content type so that when a new Snippet is created there will be a text area for us to use.  

<strong>Figure 4:</strong> Creating a new field for our new content type is easy.

Let's create a new Snippet by going to Administration > Content > Add New Content. Figure 5 shows us the new field in red. Let put some content in the Snippet - for now Title='Hello World', Body='This is a new snippet' and NewField='This is a new field'. Save this snippet. Now we are READY to move on and look at the programming side of things.

<strong>Figure 5:</strong> Creating new Snippet content on our website.

Creating a Theme Template File

Now that we have some content, let go on and look at our theme template.  We will learn how to figure out how to retreive our field information via this template's php code.   The Snippet content is just another node in Drupal and so uses the node.tpl.php template by default.   This template is a part of the Drupal core and located at: /<drupal installation root>/modules/node.  We shouldn't modify the core, so we're  going to override this core file.  For our reference, let's copy this file, and move it to our theme directory.

The template files for your theme directory will typically be located at: /<drupal installation root>/sites/all/themes/<theme name>/templates.  Copy the node.tpl.php file to this directory.  Create a new file called node--snippet.tpl.php.  This is how default templates are overridden.  In Drupal 7, a '--' is added after the 'node' followed by the name of the content type, in this case 'snippet', the machine name version of the content type name.  The general form for the override template file name that Drupal looks for is:

<drupal core type>--<custom content type>.tpl.php

So now, instead of accessing node.tpl.php, for our particular Snippet content type node--snippet.tpl.php will be used instead.  We keep a reference of the node.tpl.php file so that we can see the recommended method for formating our php code.  The node.tpl.php file also gives us useful information on some of the global variables accessible to nodes - we can use these variables in our own overridden template file.   Let's fill our node--snippet.tpl.php file with some sketleton code from node.tpl.php.

<div id="node-<?php print $node->nid; ?>"
 class="<?php print $classes; ?> clearfix"
<?php print $attributes; ?>>
// Our code here
</div>

Now.  We want to be able to access the fields from our Snippet content type so that we can use their contents to display our snippets.  BUT ... how do we know what variable names to use????  Well let's look into that next.

Determining Available Variable Names in Template Files

Unfortunately there is no proper documentation on the topic, at least no documentation that is easy to find.  Often to find out these variable names we need to look through the Drupal core code.  For this reason, I had you make a reference copy of the node.tpl.php file.  This file provides some of the global variables that will be excessible to you through your own template node--snippet.tpl.php file.  

Now another way, barring looking on the web and goin through code is to utilize the Template Field Variables module. This is a contributed module that accesses and converts some variable names into easy names for use by us in our template file.  Make note - only SOME variables!  Now, in order to use this module we need to add another file to our theme.  Specifically in the parent folder of our templates folder at location: /<drupal installation root>/sites/all/themes/<theme name>.  Here we add the file template.php if it doesn't exist.  Or if it exists, we simply modify the file.  Inside the file add the following code:

//-----------------------------------------------------------------------
// Preprocessor for node.tpl.php
//-----------------------------------------------------------------------
function weblog_preprocess_node(&$vars)
{
  // Enables simple variable names for Fields, by calling the 
  // Template Field Variable Module  ...  Set debug=true to 
  // see the new fangled variable names.
  tpl_field_vars_preprocess($vars, $vars['node'], array(
    'cleanup' => FALSE,
    'debug' => FALSE,
  ));
}

This code adds a preprocessor such that before our node template file is loaded and displayed it performs an operation on our variables and makes them visible.  When 'debug'=>FALSE our website loads up and displays as normal.  However, when 'debug'=>TRUE the Template Field Variables module displays a list of SOME of our field variables.  These variables appear in the browser window after we reload our webpage.  Before reloading the page its important to clear all caches via your web admin. page at Administration > Configuration > Performance.  After checking the variables change the debug variable back to FALSE, clear the cache and reload the page to return it back to normal.

Now, this does not work for all variables.  So another method is to go back to the node--snippet.tpl.php file and add the following code. 

// USE THIS CODE TO FIND VALUE OF KEYS FOR ACCESSING FIELD VARIABLES
$arr=field_get_items('node', $node, 'field_newfield');
foreach($arr[0] as $key => $value)
{
    $output=$output . "key=" . $key . " value=" . $value . "<br>";
} 
echo $output;

The code does essentially the same thing as the Template Field Variables module, except using Drupal's built in Field module API.  In all honest, I don't really understand the documentation for the Field API very well, its not a particularly easy or clear read.  Regardless, in the above example code we use the field_get_items() function to get the field: field_newfield as defined in our Snippet content type.  The $node variable is a global variable defined somewhere in the Drupal core - God only knows!  Notice that field_newfield is the machine name that drupal assigns the field ... drupal usually displays this machine name when you write a label, name or title into your site's web admin. interface.

Getting back to the $node variable, it is essentially a multi-dimensional array which you can access by using the following general syntax in your PHP code: 

$node->field_yourfield['yourlanguage'][0]['yourvalue'];

Confused??  You're not the only one.  Essentially replace <yourfield> with the machine name from the web interface.  <yourlanguage> is a code like 'en' for English, 'jp' for Japanese, 'und' for Undetermined, etc.  And <yourvalue> is the value within the field itself that you want to look at.  Sorry guys!  I don't really know anymore details at the moment.  Essentially, as I understand it, the field_get_items() function provides an easy method to access the $node ... or perhaps, other variables.  My suspicion is that it also gets the locale and language settings for the particular user accessing the node ... so you don't have to hardcode this value.  

In the foreach loop we construct an HTML string output to display the key and value pair for elements inside our field_newfield.  This output is then echoed to the screen.  Clearing all caches and reloading the Snippet node will display the $output variable.  Notice that we use the first element, $arr[0] array and iterate through it ... I don't know why Drupal developers decided on this convention, or even whether there is a $arr[1] element. 

Well folks!  That's that.  Once I have the comment's section of this blog enabled, feel free to leave comments .. politely worded criticisms, comments, suggestions and requests are always welcome! :)