Score:2

Shouldn't hook_update to add a new field to an entity use the field definition from the entity class?

hk flag

I was writing an update hook to add a new field to a custom entity and was following the pattern shown here

https://www.drupal.org/node/2554097

/**
 * Add 'revision_translation_affected' field to 'node' entities.
 */
function node_update_8001() {
  // Install the definition that this field had in
  // \Drupal\node\Entity\Node::baseFieldDefinitions()
  // at the time that this update function was written. If/when code is
  // deployed that changes that definition, the corresponding module must
  // implement an update function that invokes
  // \Drupal::entityDefinitionUpdateManager()->updateFieldStorageDefinition()
  // with the new definition.
  $storage_definition = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Revision translation affected'))
      ->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
      ->setReadOnly(TRUE)
      ->setRevisionable(TRUE)
      ->setTranslatable(TRUE);

  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('revision_translation_affected', 'node', 'node', $storage_definition);
}

I felt I was duplicating the BaseFieldDefinition in both the custom entity class as well as in the install file. Shouldn't I be able to use the static function

public static function baseFieldDefinitions(EntityTypeInterface $entity_type) 

from the entity class to load the field definition and install it?

No Sssweat avatar
ua flag
For historical purposes, I think it's best practice not to.
4uk4 avatar
cn flag
Yes, historical in the sense of code revisions. The code update could contain multiple changes at one time while update hooks need to process the changes step by step.
hk flag
Thanks. Got it.
Score:3
us flag

Using the object returned by Drupal::entityDefinitionUpdateManager() is the right way to update an entity fields, for the same reason an hook_update_N() implementation won't call any hook_schema() implementation to update a database field.

Imagine that you later change the entity and rename that field from revision_translation_affected to translation_affected. If the update hook you wrote now uses the array returned from baseFieldDefinitions() and stores it in $fields, it won't find any value for fields['revision_translation_affected'], since baseFieldDefinitions() has been already updated to return the renamed field.

Update hook implementations must work independently from being the last update hook added or not.
Furthermore, the code used from an update hook cannot be changed, once that hook has been added. If an update hook creates an entity field that is later removed (for example), a new update hook must be added to remove that entity field; the existing update hook cannot be changed not to add that entity field anymore, or the sites that already run that update hook won't see the entity field removed. (Drupal runs an update hook only once.)

hk flag
Thanks for the detailed explanation @apaderno. That makes total sense.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.