Technical blog and writings by Micah Webner.

Adding fake Drupal 7 node fields with custom theme functions

This example takes the node creation date and renders it as a fake field. It also creates a theme_mysite_pseudo_field() function that could be used as a template for any renderable array.

For our example, our content type is podcast, and we want to add a pseudo-field called mysite_podcast_date. This is a pretty standard implementation of hook_node_view(), but we're going to specify our mysite_pseudo_field theme wrapper and specify that we want our label to be inline. This adds our fake field to our node's output.

/** * Implements hook_node_view(). */ function mysite_node_view($node, $view_mode, $langcode) { switch ($node->type) { case 'podcast': $node->content['mysite_podcast_date'] = array( '#type' => 'item', '#field_name' => 'mysite_podcast_date', '#label' => t('Date:'), '#markup' => format_date($node->created, 'custom', 'l, F j, Y'), '#theme_wrappers' => array('mysite_pseudo_field'), '#label_display' => 'inline', ); break; } }

Next we want to add our field to hook_field_extra_fields(). This allows us to include our field in the manage fields display for our content type.

Note: While writing this, I've noticed that I hard-coded the #label_display in hook_node_view() above, and it cannot be set in the site's UI. I can't recall the details behind that, but I think it's related to #1471706 which is an open issue for Drupal 8 core.

/** * Implements hook_field_extra_fields(). */ function mysite_field_extra_fields() { $extra['node']['podcast']['display'] = array( 'mysite_podcast_date' => array( 'label' => t('Sermon Date'), 'description' => t('Display the node date like a field.'), 'weight' => 0, ), ); return $extra; }

Now we invoke hook_theme() to add information about the mysite_pseudo_field theme wrapper.

Note: This is a fairly simple example using a theme function. Here's a better example that uses a template file and a template_preprocess() function.

/** * Implements hook_theme(). */ function mysite_theme() { return array( 'mysite_pseudo_field' => array( 'render element' => 'element', ), ); }

Finally, we create our theme function, which more closely emulates Field API output than anything I've found (other than forging enough settings to use the actual field theming functions.)

/** * Theme output of a pseudo_field. * * @see */ function theme_mysite_pseudo_field($variables) { $classes = array('clearfix', 'field'); if (isset($variables['element']['#field_name'])) { $classes[] = 'field-name-' . strtr($variables['element']['#field_name'], '_', '-'); } if (isset($variables['element']['#label_display'])) { $classes[] = 'field-label-' . $variables['element']['#label_display']; } $output = '<div class="' . implode(' ', $classes) . '">'; if (isset($variables['element']['#title'])) { $output .= '<div class="field-label">' . $variables['element']['#title'] . '&nbsp;</div>'; } $output .= '<div class="field-items">' . $variables['element']['#markup'] . '</div>'; $output .= '</div>'; return $output; }


I combined several resources to figure this out. I learned about hook_node_view() from ComputerMinds: Add stuff to a node and configure it like fields.


  • April 24, 2013: Improved theme_mysite_pseudo_field() to add support for #field_name and streamline handling of #label_display, based on project collaboration with Donald Dille.
  • June 4, 2013: This commit on one of my current projects includes a template preprocess function and uses an external template file to generate the HTML for theming fake fields.