Pseudo fields are a special type of field that you can add to any content entity type. This means these fields can be added to nodes, terms, user entities, menu links, blocks, paragraphs, media entities, and any other custom entity type you might have.
The value for a regular field, which is added as a base field or via the UI, is stored in the database, but for a pseudo field, the value is generated in the code. You have full control over the field's value.
Additionally, you can drag and drop a pseudo field in the "Manage form display" or "Manage display" settings.
1. Display pseudo fields
Instead of embedding data directly into a Twig template, consider creating a new pseudo field if it suits your scenario. Using a pseudo field is a much better solution than just adding elements to your templates until they become so cluttered that you have no idea what's happening.
You can change the weight of your pseudo field or hide it completely if you don't need it later on. For example, you can show the pseudo field just on the teaser and hide it for all other displays.
Attaching a pseudo field is super simple. All you have to do is implement two hooks.
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
/**
* Implements hook_entity_extra_field_info().
*/
function MY_MODULE_entity_extra_field_info() {
$extra = [];
$extra['node']['news']['display']['field_thank_you'] = [
'label' => t('Thank You'),
'description' => t('Thank You pseudo field.'),
'weight' => 0,
'visible' => TRUE,
];
return $extra;
}
/**
* Implements hook_ENTITY_TYPE_view().
*/
function MY_MODULE_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
if ($display->getComponent('field_thank_you')) {
$thank_you_notice = \Drupal::config('MY_MODULE.settings')->get('thank_you_notice');
$build['field_thank_you'] = [
'#type' => 'markup',
'#markup' => $thank_you_notice,
];
}
}
As you can see, we are attaching a new pseudo field called "Thank You" to the News content type (bundle).
To add a pseudo field to all content types you can load all Node bundles and do something like this:
use Drupal\node\Entity\NodeType;
foreach (NodeType::loadMultiple() as $bundle) {
$extra['node'][$bundle->id()]['display']['field_thank_you'] = [
'label' => t('Thank You'),
'description' => t('Thank You pseudo field.'),
'weight' => 0,
'visible' => TRUE,
];
}
If your entity type doesn't have any bundles then use the same value for the first and second index like this:
$extra['task']['task']['display']['field_thank_you'] = [
'label' => t('Thank You'),
'description' => t('Thank You pseudo field.'),
'weight' => 0,
'visible' => TRUE,
];
The final note on displaying pseudo fields is to use the proper entity type view hook. So, if you want to add a new pseudo field, for example, to your Commerce Product entity type, then don't use the MY_MODULE_node_view() hook, but instead, use the MY_MODULE_commerce_product_view() hook.
2. Form pseudo fields
From my personal experience, pseudo fields are less used in forms, but sometimes they do come in handy. To attach a pseudo field to an entity form, you also have to implement two hooks.
use Drupal\Core\Form\FormStateInterface;
/**
* Implements hook_entity_extra_field_info().
*/
function MY_MODULE_entity_extra_field_info() {
$extra = [];
$extra['node']['news']['form']['field_thank_you'] = [
'label' => t('Thank You'),
'description' => t('Thank You pseudo field.'),
'weight' => 0,
'visible' => TRUE,
];
return $extra;
}
/**
* Implements hook_form_alter().
*/
function MY_MODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (in_array($form_id, ['node_news_form', 'node_news_edit_form'])) {
if ($form_state->get('form_display')->getComponent('field_thank_you')) {
$thank_you_notice = \Drupal::config('MY_MODULE.settings')->get('thank_you_notice');
$form['field_thank_you'] = [
'#type' => 'markup',
'#markup' => $thank_you_notice,
];
}
}
}
And let's see how this looks like assuming that $thank_you_notice variable has some string value:
Form pseudo field in combination with Field Group
If you are using a form pseudo field in combination with the Field Group module, then to have the pseudo field displayed within the field group, it is necessary to slightly modify the code and add a container like this:
/**
* Implements hook_form_alter().
*/
function MY_MODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (in_array($form_id, ['node_news_form', 'node_news_edit_form'])) {
if ($form_state->get('form_display')->getComponent('field_thank_you')) {
$thank_you_notice = \Drupal::config('MY_MODULE.settings')->get('thank_you_notice');
$form['field_thank_you'] = [
'#type' => 'container'
];
$form['field_thank_you']['value'] = [
'#type' => 'markup',
'#markup' => $thank_you_notice,
];
}
}
}
Otherwise, the pseudo field will be displayed outside the field group and will look odd. Thanks to Stefan Korn for bringing this to my attention.
Summary
One drawback of pseudo fields is that you can't display them in a View if you want to show single fields. You have to configure your View to display content and choose an appropriate view mode.
You can overcome this limitation by creating a field plugin for Views. In that case, it makes sense to move the field logic to a service class to avoid writing the same code twice, once in the hook_ENTITY_TYPE_view() hook and once in the field plugin.
You can print a pseudo field in a Twig template just like any other field:
{{ content.field_thank_you }}
And that's pretty much it. Now you know what pseudo fields are and how to add them to entity displays and forms.