Skip to main content

Pseudo fields in Drupal 8

Drupal 8 pseudo field

Let's say that you have a content type named City in your Drupal 8 website. This content type may have standard information about a city like name, postal code, flag, coordinates, etc. All these fields are clearly defined and they don't change over time. But what if you want to show the current temperature in a city as well. How would you do this, since this information is changing over time? You cannot just create a text field and enter the current temperature and forget about it.

You can come up with some creative way to do this, but since this information is a part of the City content type it should live together with other information about the city. The best way to accomplish this is to implement a pseudo field and use some weather service to dynamically fetch the current temperature.

Pseudo field is a field that you can attach to any content entity type. For example, you can add a pseudo field to nodes, users, taxonomy terms, paragraphs, and so on. A good example of the pseudo field that comes with the Drupal 8 core is the Links field. You can hide this field in the UI, but you cannot change it's value, because the content of this field is generated in the code. 

To attach a pseudo field, you need to implement only two hooks. Yeah, it's that simple.

/**
 * Implements hook_entity_extra_field_info().
 */
function MODULE_NAME_entity_extra_field_info() {
  $extra_field = [];
  
  $extra_field['node']['article']['display']['field_some_field'] = [
    'label' => t('Pseudo field label'),
    'description' => t('Description of the pseudo field.'),
    'weight' => 100,
    'visible' => TRUE,
  ];

  return $extra_field;
}

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function MODULE_NAME_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($view_mode == 'full') {
    if ($display->getComponent('field_some_field')) {
      $build['field_some_field'] = [
        '#type' => 'markup',
        '#markup' => 'Some pseudo field content', 
      ];
    }
  }
}

You also to need to add two classes to the "use" clauses of your .module file:

use \Drupal\Core\Entity\EntityInterface;
use \Drupal\Core\Entity\Display\EntityViewDisplayInterface;

As you can see, I attached a psuedo field named 'field_some_field' to the Article entity so you can test this easily. Just paste the code in your .module file, flush all caches and go the following page: "admin/structure/types/manage/article/display" where you will see your new field.

Content editors can hide or show this field in display settings of the entity, but the value of this field cannot be changed from the user interface. So, by using pseudo fields, you get all the benefits that other fields created from the UI have, like drag and drop functionality to control visibility and position, but at the same time you can dynamically generate its content.

Pseudo field's value can be any renderable array, and that means that you can return whatever you want, like block, view, form or even another entity. Let's see how easy is to render user login form in a pseudo field:

function MODULE_NAME_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($view_mode == 'full') {
    if ($display->getComponent('field_some_field')) {
      $build['field_some_field'] = \Drupal::formBuilder()->getForm('\Drupal\user\Form\UserLoginForm');
    }
  }
}

Isn't this amazing. I think it is, so the next when you need to display some data that clearly belongs to your entity, but its value has to be generated from the code, please consider using this approach. You definitely won't regret it.