Adding fields to custom entities programmaticallyfor Drupal 8 , 9 , 10 , and 11

Last updated :  

Introduction

In the previous lesson, we set up storage, access, and form handlers for our custom entity called Contact Message. Now that our entity is fully operational within the Drupal framework, it's time to enhance its functionality by adding custom fields programmatically, fitting particular data and content needs.

Why Add Fields Programmatically?

Adding fields programmatically ensures consistency and automation in entity creation, very useful when deploying across environments. It allows developers to script installations that automatically add the necessary fields, reducing manual steps and potential configuration errors.

Field API Overview

Drupal’s Field API provides the means to define fields, attach them to entities, configure their properties, and manage how they are displayed. Essential components include:

  • Base Fields: Defined in the entity class and applied to all instances of an entity type.
  • Configurable Fields: Managed via the UI, allowing administrators to create new fields via the field administration interface.
Reminder: Base fields are intended for properties all entities share, whereas configurable fields cater to use cases needing flexibility.

Adding Base Fields Programmatically

Base fields are part of the entity itself, implemented directly in the entity class. Here's how you can add them to your custom entity:

Modify Entity Class

Continuing from your ContactMessage entity (src/Entity/ContactMessage.php), modify the baseFieldDefinitions method:

public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
  $fields = parent::baseFieldDefinitions($entity_type);
  
  $fields['name'] = BaseFieldDefinition::create('string')
    ->setLabel(t('Name'))
    ->setDescription(t('The name of the Contact Message.'))
    ->setRequired(TRUE)
    ->setSettings(['max_length' => 50])
    ->setDisplayOptions('form', ['type' => 'string_textfield', 'weight' => 0]);

  $fields['email'] = BaseFieldDefinition::create('email')
    ->setLabel(t('Email'))
    ->setDescription(t('Contact email address.'))
    ->setRequired(TRUE)
    ->setDisplayOptions('form', ['type' => 'email_default', 'weight' => 1]);

  $fields['message'] = BaseFieldDefinition::create('text_long')
    ->setLabel(t('Message'))
    ->setDescription(t('The message content.'))
    ->setDisplayOptions('form', ['type' => 'text_textarea', 'weight' => 2]);

  // Add a new timestamp field for when the message was submitted.
  $fields['submitted'] = BaseFieldDefinition::create('created')
    ->setLabel(t('Submitted time'))
    ->setDescription(t('The time that the contact message was submitted.'))
    ->setDisplayOptions('form', ['type' => 'datetime_timestamp', 'weight' => 3]);

  return $fields;
}

In this example, we added a submitted timestamp field to track when messages are submitted.

Adding Configurable Fields Programmatically

Although base fields are defined in the code, configurable fields can also be set programmatically though typically via UI. Here’s how to do the latter if there are specific scenarios you control via deployment scripts:

Use Update Hooks

Add configurable fields using update hooks in your module's .install file:

function custom_module_update_8001() {
  // Load the entity type manager service.
  $entity_type_manager = \Drupal::entityTypeManager();
  
  // Define a field storage configuration (Field storage defines the field level settings).
  $field_storage = FieldStorageConfig::create([
    'field_name' => 'phone_number',
    'entity_type' => 'contact_message',
    'type' => 'string',
    'settings' => [
      'max_length' => 15,
    ],
  ]);
  $field_storage->save();

  // Define a field configuration (Field config defines how a field should behave).
  $field_instance = FieldConfig::create([
    'field_storage' => $field_storage,
    'bundle' => 'contact_message',
    'label' => t('Phone Number'),
    'settings' => [],
  ]);
  $field_instance->save();
}

This script automates the creation of a phone_number field for the Contact Message entity.

Conclusion

Adding fields programmatically to your custom entities enhances flexibility and automation within Drupal's modular structure. Understanding how and when to implement base versus configurable fields will empower you to design more powerful, feature-rich modules that cater to specific project demands.

Teaser for the Next Lesson

With a solid foundation in creating and augmenting custom entities, you're ready to delve into querying them efficiently. The next lesson will explore utilizing entity.query for custom entity queries, optimizing data retrieval. Don't miss it!