7.x field.api.php hook_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays)

Allow formatters to load information for field values being displayed.

This should be used when a formatter needs to load additional information from the database in order to render a field, for example a reference field which displays properties of the referenced entities such as name or type.

This hook is called after the field type's own hook_field_prepare_view().

Unlike most other field hooks, this hook operates on multiple entities. The $entities, $instances and $items parameters are arrays keyed by entity ID. For performance reasons, information for all available entities should be loaded in a single query where possible.

Parameters

$entity_type: The type of $entity.

$entities: Array of entities being displayed, keyed by entity ID.

$field: The field structure for the operation.

$instances: Array of instance structures for $field for each entity, keyed by entity ID.

$langcode: The language the field values are to be shown in. If no language is provided the current language is used.

$items: Array of field values for the entities, keyed by entity ID.

$displays: Array of display settings to use for each entity, keyed by entity ID.

Return value

Changes or additions to field values are done by altering the $items parameter by reference.

Related topics

2 functions implement hook_field_formatter_prepare_view()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

field_test_field_formatter_prepare_view in modules/field/tests/field_test.field.inc
Implements hook_field_formatter_prepare_view().
taxonomy_field_formatter_prepare_view in modules/taxonomy/taxonomy.module
Implements hook_field_formatter_prepare_view().

File

modules/field/field.api.php, line 1149
Hooks provided by the Field module.

Code

function hook_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
  $tids = array();

  // Collect every possible term attached to any of the fieldable entities.
  foreach ($entities as $id => $entity) {
    foreach ($items[$id] as $delta => $item) {

      // Force the array key to prevent duplicates.
      $tids[$item['tid']] = $item['tid'];
    }
  }
  if ($tids) {
    $terms = taxonomy_term_load_multiple($tids);

    // Iterate through the fieldable entities again to attach the loaded term
    // data.
    foreach ($entities as $id => $entity) {
      $rekey = FALSE;
      foreach ($items[$id] as $delta => $item) {

        // Check whether the taxonomy term field instance value could be loaded.
        if (isset($terms[$item['tid']])) {

          // Replace the instance value with the term data.
          $items[$id][$delta]['taxonomy_term'] = $terms[$item['tid']];
        }
        else {
          unset($items[$id][$delta]);
          $rekey = TRUE;
        }
      }
      if ($rekey) {

        // Rekey the items array.
        $items[$id] = array_values($items[$id]);
      }
    }
  }
}

Comments

ivanjaros’s picture

Seems this hook can be used only by the module that defines a field(formatter).

sanguis’s picture

which is unfortunate because if one needs to make a custom taxonomy formatter then need to reproduce the entire taxonomy hook in your own function to do so.

John Pitcairn’s picture

You should be able to implement the hook and just call taxonomy module's version of it?

doitDave’s picture

You are suggesting a WA (thanks, and that's in fact how it is done), while the criticism on the suboptimal design is still valid.

What for would I offer a (such a) hook if not in order for other modules to hook into the flow. Looks like the original designer was mislead a bit here.

Reno Greenleaf’s picture

Created custom formatter for existing field type. Added this hook. It's not called.
Tried to add it to a module that declares field type. It's not called.
Currently using Drupal 7.38.
Did anyone try the hook? Does this thing work at all?

erwangel’s picture

Hmmm... It used to work at least until 7.37 but after upgrading to 7.39 it seems it's no more working :(
What I'm doing now is calling hook_field_formatter_prepare_view manually inside the hook_field_formatter_view:

//inspired by the media_gallery_item_view function in media_gallery.fields.inc

$formatter = field_info_formatter_types($display['type']);
$function = $formatter['module'] . '_field_formatter_prepare_view';
if (function_exists($function)) {
$items_multi = array($entity->nid => &$items); // Taken by reference, so can't inline.
$function('node', array($entity->nid => $entity), $field, array($entity->nid => $instance), $langcode, $items_multi, array($entity->nid => $display));
}

inavarre’s picture

Was working for me fine until the last security update :(

glass.dimly’s picture

The modules that this hook calls differ on a per-field basis (on Drupal 7.50, at least).

They are limited to modules whose field formatters are possible for use on the current field type. For instance, if I declare in hook_field_formatter_info that my formatter applies to text fields only, then my module's implementation of hook_field_formatter_prepare_view will be called only for text fields.

To repeat, if your module does not implement hook_field_formatter_info and your entity does not have an field eligible for theming by that display formatter, then hook_field_formatter_prepare_view will not be called on that entity.

Behold:

function field_default_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $display) {
  // Group entities, instances and items by formatter module.
  $modules = array();
  foreach ($instances as $id => $instance) {
    if (is_string($display)) {
      $view_mode = $display;
      $instance_display = field_get_display($instance, $view_mode, $entities[$id]);
    }
    else {
      $instance_display = $display;
    }

    if ($instance_display['type'] !== 'hidden') {
      $module = $instance_display['module'];
      $modules[$module] = $module;
      $grouped_entities[$module][$id] = $entities[$id];
      $grouped_instances[$module][$id] = $instance;
      $grouped_displays[$module][$id] = $instance_display;
      // hook_field_formatter_prepare_view() alters $items by reference.
      $grouped_items[$module][$id] = &$items[$id];
    }
  }

  foreach ($modules as $module) {
    // Invoke hook_field_formatter_prepare_view().
    $function = $module . '_field_formatter_prepare_view';
    if (function_exists($function)) {
      $function($entity_type, $grouped_entities[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $grouped_displays[$module]);
    }
  }
}