Entity display: The basics

Last updated on
22 December 2017

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

1. Intro

Through the implementation of hooks, developers will be able to define how entities are rendered. The advantages of this approach are:

  • High flexibility
    • We can define displays by entity, content type, view mode, etc.
    • Definitions can be altered. Modules can override the display defined previously by another module.
  • Developers only need to include a basic logic.
  • Drupal rules. The use of hooks, following the standard behaviour of Drupal 7 will allow developers to understand how it works. In fact, the solution is based on the implementation of the hook hook_entity_view.

2. Cache

It is important to notice any display configuration defined through this system (next sections will go through this point in more detail) will be cached and changes won't be available straight away. The system implements its own cache table entity-display so it can be cleared separately through Drushdrush cc entity-display.

3. Defining the display

The hook hook_entity_display()will allow developers to define the elements forming the display for entities. This means:

  • Select visible (and no visible) rendering elements (fields and theme elements) using their unique name.

  • Specify how the selected fields are rendered, through the field formatter (fields) or render array (theme elements).

The hook must return an array of visible elements (key) and their display configuration (value). Not included elements won’t be rendered (they will be considered as hidden). These display configurations (or display elements) are specifications of the settings used for the element, defined by the hooks hook_entity_display_field_formatter()in case of fields and hook_entity_display_render_element()for non-field elements.

As usual, it's encouraged to use the module name as prefix of the returned array keys to avoid naming collision.

entity_display.api.php

/**
 * Define an entity display.
 *
 * The goal of this hook is to define how an entity is render:
 *   - Displayed fields. Only the included fields will be displayed.
 *   - Element definition. Specify how the elements are displayed, using
 *     field formatter and render element definitions defined by
 *     hook_entity_display_field_formatter() and
 *     hook_entity_display_render_element().
 *
 * @param array $display_elements
 *   Elements already included in the display. It is passed by reference to
 *   allow its modification.
 * @param string $entity
 *   Entity whose display is being created.
 * @param string $type
 *   Entity type (node, user, etc).
 * @param string $view_mode
 *   Display view mode.
 */
function hook_entity_display(&$display_elements, $entity, $type, $view_mode) {
  // This is an example how we could set the display of the view mode 'teaser'
  // for nodes of any type.
  if ($type == 'node' && $view_mode == 'teaser') {
    $display_elements = array(
      'title_field'        => 'module_name_smart_trimmer_title',
      'short_title'        => 'module_name_trimmer_10_title',
      'field_content_date' => 'module_name_date_time_picker',
      'field_brand_ref'    => 'module_name_entity_display_full',
    );
  }
  // Or how we could include the author biography in the display of nodes of
  // type 'article' (referencing the render element configuration 'user_bio').
  if ($type == 'node' && $view_mode == 'full') {
    $content_type = $entity->type;
    if ($content_type == 'article') {
      $display_elements['footer_author'] = 'module_name_user_bio';
    }
  }
  // Or how we could show the user full name through the render element
  // configuration 'user_full_name' in the view mode 'teaser'.
  if ($type == 'user' && $view_mode == 'teaser') {
    $display_elements['user_profile_full_name'] = 'module_name_user_full_name';
  }
  // This is as flexible as we want...
}

IMPORTANT

The display array ($display_elements) is passed by reference. It contains previously declared elements to be included in the display that can be, therefore, overridden. Thus, the elements included in the current implementation can be modified by other modules.

Hook location

In order to maintain a structured, scalable product, it is encouraged to locate hooks implementing display definitions (entities, field formatters or render elements) in a separate folder namedentity_display.

Specifically, entity display definitions (hook_entity_display) will need to be located in the file  <module_name>.entity_display.inc

Though the hook will be automatically loaded from this file, we'll need to declare its inclusion in the main module file:

<module_name>.module

<?php

/**
 * @file
 * Main module file.
 */

module_load_include('render_elements.inc', '<module_name>', 'entity_display/<module_name>');
module_load_include('entity_display.inc', '<module_name>', 'entity_display/<module_name>');
module_load_include('field_formatters.inc', '<module_name>', 'entity_display/<module_name>');

Default view mode

In order to emulate the current view modes logic, we'll be able to define 'default' view modes. The (three-dimensions) variable 'entity_display_default_display' will contain a list of view modes resorting to the default definition. 

Example

After updating the variables as follows:

$default_display = variable_get('entity_display_default_display', array());
$default_display['node']['article']['full'] = TRUE;
variable_set('entity_display_default_display', $default_display);

The display of 'node' entities, 'article' bundle, in the view mode 'full' will use the default display configuration defined by the view mode 'default', for example:

/**
 * Implementshook_entity_display().
 */
function module_name_entity_display(&$display_elements, $entity, $type, $view_mode) {
  // Every bundle of the entity node will include the following fields.
  if ($type == 'node' && $view_mode == 'default') {
    $display_elements = array(
      'body_field'         => 'module_name_default_text',
      'webform'            => 'entity_display_extra_field',
    );
  }
}

4. Defining field formatters

Field formatter definitions are an abstraction of the settings used to display a field in a specific way, e.g. the configuration used in the Manage display UI exported to code:

Field in Manage display UI

  • Content type: Article
  • View mode: Full
  • Field: Content date

Field formatter - Manage display

Field formatter definition in code

$formatter_conf = array(
  'type' => 'date_default',
  'label' => 'hidden',
  'settings' => array(
    'format_type' => 'pp_short',
    'fromto' => 'both',
    'multiple_from' => '',
    'multiple_number' => '',
    'multiple_to' => '',
    'show_remaining_days' => FALSE,
  ),
);

Hook entity_display_field_formatter

The hook hook_entity_display_field_formatter() will allow developers to define the formatters (display settings) to be used for fields. A formatter definition must include:

  • The formatter type.

  • Specific settings for the formatter type.

  • Label. Its position or 'hidden'.

An array with the specifications of every formatter must be returned. Formatter keys must be unique in the system, so it is encouraged to use as naming: <module_name>_<our_formatter_name>

entity_display.api.php

/**
 * Define field formatters to be used in hook_entity_display().
 *
 * Every formatter will follow the standard Drupal specification for field
 * displays:
 *  - 'type': The name of the formatter to use.
 *  - 'settings': The array of formatter settings.
 *  - 'label': The position of the field label or 'hidden'.
 *
 * @param array $formatters
 *   List of defined field formatters so far by other modules. The argument
 *   is passed by reference to allow other modules to override/unset values.
 */
function hook_entity_display_field_formatter(&$formatters) {
  // Field formatter to trim the field value (HTML) to 50 characters including
  // ellipsis.
  $formatters['module_name_smart_trimmer_title'] = array(
    'type' => 'smart_trim_format',
    'settings' => array(
      'trim_length' => 50,
      'trim_suffix' => '...',
    ),
  );

  // Field formatter to trim the field value (plain text) to 10 characters.
  $formatters['module_name_trimmer_10_title'] = array(
    'type' => 'trimmer',
    'settings' => array(
      'trim_length' => 10,
    ),
  );

  // This formatter creates the 'full' display of the referenced entity.
  $formatters['module_name_entity_display_full'] = array(
    'type' => 'entityreference_entity_view',
    'label' => 'above',
    'settings' => array(
      'links' => 0,
      'view_mode' => 'full',
    ),
  );
}

How to define the formatter settings

To know the available options (and default values) for the settings of a formatter can be useful to have a look at the code defining a field formatter, hook_field_formatter_info()

date.module 

/**
 * Implements hook_field_formatter_info().
 */
function date_field_formatter_info() {
  $formatters = array(
    'date_default' => array(
      'label' => t('Date and time'),
      'field types' => array('date', 'datestamp', 'datetime'),
      'settings' => array(
        'format_type' => 'long',
        'multiple_number' => '',
        'multiple_from' => '',
        'multiple_to' => '',
        'fromto' => 'both',
        'show_remaining_days' => FALSE,
      ),
    ),
    'format_interval' => array(
      'label' => t('Time ago'),
      'field types' => array('date', 'datestamp', 'datetime'),
      'settings' => array(
        'interval' => 2,
        'interval_display' => 'time ago',
      ),
    ),
    'date_plain' => array(
      'label' => t('Plain'),
      'field types' => array('date', 'datestamp', 'datetime'),
    ),
  );
  return $formatters;
}

To know the actual formatter settings used by a field using the standard display system and export it, the Drush command: entity-display-get-field-display comes in handy. Which will be run through on the last chapter of the guide.

Placing formatter definitions

Again, it is encouraged to place formatter definitions in a separate file in the display folder:<module_name>.entity_display_field_formatter.inc

IMPORTANT

Extra fields are included in the display in a special way as they don't actually use any formatter settings. They can be directly included in the entity display using the "placeholder" configuration 'entity_display_extra_field':

/**
 * Implements hook_entity_display().
 */
function module_name_entity_display_node_full(&$display_elements, $entity_type, $bundle, $view_mode) {

  if (($entity_type == 'node' && $view_mode == 'full') && ($bundle == 'article' || $bundle == 'blog')) {
    $display_elements['webform'] = 'entity_display_extra_field';
  }
}

5. Defining render element configurations

Following the same development guideline to define field formatters, the hook hook_entity_display_render_element will allow developers to specify the display of non-field elements in the file <module_name>.entity_display_render_element.inc

In this case, through render arrays:

entity_display.api.php


/**
 * Define render element configurations to be used in hook_entity_display().
 *
 * Every configuration will follow the standard Drupal specification of render
 * arrays:
 *  - '#theme': The name of the theme element.
 *  - '#cache': Cache settings.
 *  ...
 *
 * @param array $render_elements
 *   List of defined render elements so far by other modules. The argument
 *   is passed by reference to allow other modules to override/unset values.
 */
function hook_entity_display_render_element(&$render_elements) {
  $render_elements['module_name_user_bio'] = array(
    '#theme' => 'user_profile_biography',
    '#cache' => array(
      'keys' => array('module_name', 'user_bio'),
      'bin' => 'cache',
      'expire' => time() + 120,
      'granularity' => DRUPAL_CACHE_PER_PAGE,
    ),
  );

  $render_elements['module_name_user_full_name'] = array(
    '#theme' => 'user_profile_name',
    // No cache as this element can be included more that once in the same page
    // for different users.
  );
}

Though a large amount of information about render arrays can be found online, e.g:

the next section we'll include several approaches to different possible scenarios integrating render arrays with the entity display system. This is a must-read as it includes some important aspects of how the entity display system works.

Help improve this page

Page status: No known problems

You can: