Entity reference computed field example in Drupal

Last updated on 14/04/2019

A computed field is a nice standartized feature of Drupal 8.

Have a look at the example on drupal.org as here I'll just give an example of how to create one which acts as entity reference field.

Basically, the porpose of my computed field is to store some Taxonomy Term(custom conditions are involved) references which I'm using for indexing with Search API.

First, we need to define the field.

File:

mymodule.module

use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\mymodule\Plugin\Field\FieldType\MyFieldComputed;
 
/**
 * Implements hook_entity_base_field_info_alter().
 *
 * {@inheritdoc}
 */
function mymodule_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
  // A computed field to store customly detected Taxonomy Term references.
  $fields['my_field_name'] = BaseFieldDefinition::create('entity_reference')
    ->setName('my_field_name')
    ->setLabel('My Computed field')
    ->setSetting('target_type', 'taxonomy_term')
    // The Entity Type this field belongs to.
    ->setTargetEntityTypeId('node')
    // The Entity Type bundle this field belongs to.
    ->setTargetBundle('person')
    ->setDescription(t('My Computed field description.'))
    ->setComputed(TRUE)
    ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
    ->setRevisionable(FALSE)
    ->setTranslatable(FALSE)
    ->setClass(MyFieldComputed::class);
}

Second and last, we need to create the computed field Class itself referenced above (MyFieldComputed).

File:

mymodule/src/Plugin/Field/FieldType/MyFieldComputed.php
<?php
 
namespace Drupal\mymodule\Plugin\Field\FieldType;
 
use Drupal\Core\Field\EntityReferenceFieldItemList;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\Core\TypedData\ComputedItemListTrait;
 
/**
 * Class for `my_field_name` computed field.
 */
class GroupsFacetTailedComputed extends EntityReferenceFieldItemList {
 
  use ComputedItemListTrait;
 
  /**
   * Field name holding the group type.
   */
  const GROUP_TYPE_FIELD_NAME = 'field_group_type_internal';
 
  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;
 
  /**
   * {@inheritdoc}
   */
  public function __construct(DataDefinitionInterface $definition, $name, TypedDataInterface $parent) {
    parent::__construct($definition, $name, $parent);
    $this->entityTypeManager = \Drupal::entityTypeManager();
  }
 
  /**
   * Compute the values.
   */
  protected function computeValue() {
 
    $entity = $this->getEntity();
    if ($entity->hasField('field_group')) {
 
      /** @var \Drupal\taxonomy\TermStorage $taxonomyStorage */
      $taxonomyStorage = $this->entityTypeManager->getStorage('taxonomy_term');
 
      $groupFieldTerms = $entity->get('field_group')->referencedEntities();
      $key = 0;
      foreach (array_values($groupFieldTerms) as $groupFieldTerm) {
        // Load and save all the parents of the chosen term.
        $parents = $taxonomyStorage->loadAllParents($groupFieldTerm->id());
 
        // Populate field values.
        foreach (array_values($parents) as $parentTerm) {
          /** @var \Drupal\taxonomy\TermInterface $parentTerm */
          if ($parentTerm->get(self::GROUP_TYPE_FIELD_NAME)->value === 'group') {
            $this->list[$key] = $this->createItem($key, $parentTerm->id());
            ++$key;
          }
        }
      }
 
    }
  }
 
}