Returns a renderable array for the value of a single field in an entity.
The resulting output is a fully themed field with label and multiple values.
This function can be used by third-party modules that need to output an isolated field.
The function takes care of invoking the prepare_view steps. It also respects field access permissions.
\Drupal\Core\Entity\EntityInterface $entity: The entity containing the field to display.
$field_name: The name of the field to display.
$display_options: Can be either:
$langcode: (Optional) The language code the field values are to be shown in. The site's current language fallback logic will be applied when no values are available for the given language code. If no language code is provided the current language will be used.
A renderable array for the field value.
function field_view_field(EntityInterface $entity, $field_name, $display_options = array(), $langcode = NULL) {
$output = array();
$bundle = $entity
->bundle();
// Return nothing if the field doesn't exist.
$instance = field_info_instance($entity
->entityType(), $field_name, $bundle);
if (!$instance) {
return $output;
}
// Get the formatter object.
if (is_string($display_options)) {
$view_mode = $display_options;
$formatter = entity_get_render_display($entity, $view_mode)
->getFormatter($field_name);
}
else {
$view_mode = '_custom';
// hook_field_attach_display_alter() needs to receive the 'prepared'
// $display_options, so we cannot let preparation happen internally.
$field = field_info_field($field_name);
$formatter_manager = drupal_container()
->get('plugin.manager.field.formatter');
$display_options = $formatter_manager
->prepareConfiguration($field['type'], $display_options);
$formatter = $formatter_manager
->getInstance(array(
'instance' => $instance,
'view_mode' => $view_mode,
'prepare' => FALSE,
'configuration' => $display_options,
));
}
if ($formatter) {
$display_langcode = field_language($entity, $field_name, $langcode);
$items = array();
// Ensure the BC entity is used.
$entity = $entity
->getBCEntity();
if (isset($entity->{$field_name}[$display_langcode])) {
$items = $entity->{$field_name}[$display_langcode];
}
// Invoke prepare_view steps if needed.
if (empty($entity->_field_view_prepared)) {
$id = $entity
->id();
// First let the field types do their preparation.
$options = array(
'field_name' => $field_name,
'langcode' => $display_langcode,
);
$null = NULL;
_field_invoke_multiple('prepare_view', $entity
->entityType(), array(
$id => $entity,
), $null, $null, $options);
// Then let the formatter do its own specific massaging.
$items_multi = array(
$id => array(),
);
if (isset($entity->{$field_name}[$display_langcode])) {
$items_multi[$id] = $entity->{$field_name}[$display_langcode];
}
$formatter
->prepareView(array(
$id => $entity,
), $display_langcode, $items_multi);
$items = $items_multi[$id];
}
// Build the renderable array.
$result = $formatter
->view($entity, $display_langcode, $items);
// Invoke hook_field_attach_view_alter() to let other modules alter the
// renderable array, as in a full field_attach_view() execution.
$context = array(
'entity' => $entity,
'view_mode' => $view_mode,
'display_options' => $display_options,
'langcode' => $display_langcode,
);
drupal_alter('field_attach_view', $result, $context);
if (isset($result[$field_name])) {
$output = $result[$field_name];
}
}
return $output;
}