Entity baseFieldDefinitions fields examples in Drupal 8

Posted: Nov 14, 2019
By: Igor
Category: Drupal

Let's take a look at a method baseFieldDefinitions and its abilities today.

Base fields are non-configurable fields that always exist on a given entity type, like the node title or created and changed dates. By definition, base fields are fields that exist for every bundle.

Entity types define their base fields in a static method baseFieldDefinitions on the entity class. The definitions returned by this function can be overridden for all bundles by hook_entity_base_field_info_alter() or overridden on a per-bundle basis via 'base_field_override' configuration entities.

For a demonstration of baseFieldDefinitions capabilities, we need to create a new module with a custom entity. For this, I will use the Drupal console.

Create a module:

drupal generate:module

 // Welcome to the Drupal module generator

 Enter the new module name:
 > Demo Entity

 Enter the module machine name [demo_entity]:
 > demo_entity

 Enter the module Path [/modules/custom]:
 > /modules/custom

 Enter module description [My Awesome Module]:
 > Module for baseFieldDefinitions examples

 Enter package name [Custom]:
 > Custom

 Enter Drupal Core version [8.x]:
 > 8.x

 Do you want to generate a .module file (yes/no) [yes]:
 > no

 Define module as feature (yes/no) [no]:
 > no

 Do you want to add a composer.json file to your module (yes/no) [yes]:
 > no

 Would you like to add module dependencies (yes/no) [no]:
 > no

 Do you want to generate a unit test class (yes/no) [yes]:
 > no

 Do you want to generate a themeable template (yes/no) [yes]:
 > no

 Do you confirm generation? (yes/no) [yes]:
 > yes

Generated or updated files

 1 - /var/www/drupalvm/drupal/web/modules/custom/demo_entity/demo_entity.info.yml

Create a content entity in the new module:

drupal generate:entity:content

 // Welcome to the Drupal Content Entity generator
 Enter the module name [admin_toolbar]:
 > demo_entity

 Enter the class of your new content entity [DefaultEntity]:
 > DemoEntity

 Enter the machine name of your new content entity [demo_entity]:
 > demo_entity

 Enter the label of your new content entity [Demo entity]:
 > Demo entity

 Enter the base-path for the content entity routes [/admin/structure]:
 > /admin/structure

 Do you want this (content) entity to have bundles (yes/no) [no]:
 > no

 Is your entity translatable (yes/no) [yes]:
 > no

 Is your entity revisionable (yes/no) [yes]:
 > no

Generated or updated files

 1 - modules/custom/demo_entity/demo_entity.permissions.yml
 2 - modules/custom/demo_entity/demo_entity.links.menu.yml
 3 - modules/custom/demo_entity/demo_entity.links.task.yml
 4 - modules/custom/demo_entity/demo_entity.links.action.yml
 5 - modules/custom/demo_entity/src/DemoEntityAccessControlHandler.php
 6 - modules/custom/demo_entity/src/Entity/DemoEntityInterface.php
 7 - modules/custom/demo_entity/src/Entity/DemoEntity.php
 8 - modules/custom/demo_entity/src/DemoEntityHtmlRouteProvider.php
 9 - modules/custom/demo_entity/src/Entity/DemoEntityViewsData.php
 10 - modules/custom/demo_entity/src/DemoEntityListBuilder.php
 11 - modules/custom/demo_entity/src/Form/DemoEntitySettingsForm.php
 12 - modules/custom/demo_entity/src/Form/DemoEntityForm.php
 13 - modules/custom/demo_entity/src/Form/DemoEntityDeleteForm.php
 14 - modules/custom/demo_entity/demo_entity.page.inc
 15 - modules/custom/demo_entity/templates/demo_entity.html.twig

Check in the demo_entity/src/Entity/DemoEntity.php – public static function baseFieldDefinitions, Drupal console have created user_id, name, status, created and changed fields. All these fields will be inside demo_entity table in DB.

Also, 'parent::baseFieldDefinitions($entity_type);' provides id and uuid fields.

 /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    $fields['user_id'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Authored by'))
      ->setDescription(t('The user ID of author of the Demo entity entity.'))
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setDisplayOptions('view', [
        'label' => 'hidden',
        'type' => 'author',
        'weight' => 0,
      ])
      ->setDisplayOptions('form', [
        'type' => 'entity_reference_autocomplete',
        'weight' => 5,
        'settings' => [
          'match_operator' => 'CONTAINS',
          'size' => '60',
          'autocomplete_type' => 'tags',
          'placeholder' => '',
        ],
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['name'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Name'))
      ->setDescription(t('The name of the Demo entity entity.'))
      ->setSettings([
        'max_length' => 50,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['status'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Publishing status'))
      ->setDescription(t('A boolean indicating whether the Demo entity is published.'))
      ->setDefaultValue(TRUE);

    $fields['created'] = BaseFieldDefinition::create('created')
      ->setLabel(t('Created'))
      ->setDescription(t('The time that the entity was created.'));

    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setLabel(t('Changed'))
      ->setDescription(t('The time that the entity was last edited.'));

    return $fields;
  }

Drupal core has the following field types:

  • boolean
  • changed
  • created
  • decimal
  • email
  • entity_reference
  • float
  • integer
  • language
  • map
  • password
  • string
  • string_long
  • timestamp
  • uri
  • uuid
  • comment
  • datetime
  • file
  • image
  • link
  • list_float
  • list_integer
  • list_string
  • path
  • telephone
  • text
  • text_long
  • text_with_summary

Below you can find examples with most of these types of fields.

entity_reference field

$fields['user_id'] is an example of entity_reference field.

The default widget – entity_reference_autocomplete, the default formatter – entity_reference_label. In settings, you can set the entity type for auto-complete. Also, you can set a handler (the examples of creating custom handlers you can find here).

With setDisplayOptions config, we can set options for the field widget (display context – form) and the field formatter (display context – view).

For better understanding, see another example with a node entity:

  $fields['article'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Article'))
      ->setDescription(t('Article related to demo entity.'))
      ->setSetting('target_type', 'node')
      ->setSetting('handler', 'default:node')
      ->setSetting('handler_settings', [
        'target_bundles' => ['article' => 'article'],
        'auto_create' => FALSE,
      ])
      ->setRequired(TRUE)
      ->setTranslatable(FALSE)
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'string',
        'weight' => 2,
      ])
      ->setDisplayOptions('form', [
        'type' => 'entity_reference_autocomplete',
        'weight' => 2,
        'settings' => [
          'match_operator' => 'CONTAINS',
          'size' => '60',
          'placeholder' => 'Enter here article title...',
        ],
      ])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE);

Note that we can set target_bundles in handler_settings.

String field

$fields['name'] – is an example of a string field.

This field contains a plain string value. The default widget is string_textfield, and the default formatter – string.

string_long field

Also, we can create a string_long field that can contain a long string value. The default widget is string_textarea, the default formatter – basic_string.

  $fields['notes'] = BaseFieldDefinition::create('string_long')
      ->setLabel(t('Notes'))
      ->setDescription(t('Example of string_long field.'))
      ->setDefaultValue('')
      ->setRequired(FALSE)
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'basic_string',
        'weight' => 5,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textarea',
        'weight' => 5,
        'settings' => ['rows' => 4],
      ])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE);

boolean field

If an entity field contains a boolean value, the default widget is boolean_checkbox, the default formatter – boolean.

   $fields['status'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Publishing status'))
      ->setDescription(t('A boolean indicating whether the Demo entity is published.'))
      ->setDefaultValue(TRUE)
      ->setSettings(['on_label' => 'Published', 'off_label' => 'Unpublished'])
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'boolean',
        'weight' => 2,
      ])
      ->setDisplayOptions('form', [
        'type' => 'boolean_checkbox',
        'weight' => 2,
      ])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE);

list_integer, list_float, list_string fields

These fields come from the options module and basically similar, so it is enough to demonstrate the use of one of them.

All these fields have options_select as the default widget and list_default as the default formatter. 

 $fields['http_status'] = BaseFieldDefinition::create('list_integer')
      ->setLabel(t('HTTP status code'))
      ->setDescription(t('Hypertext Transfer Protocol (HTTP) response status codes.'))
      ->setDefaultValue(200)
      ->setSettings([
        'allowed_values' => [
          200 => 'OK',
          201 => 'Created',
          202 => 'Accepted',
          300 => 'Multiple Choices',
          301 => 'Moved Permanently',
          302 => 'Moved Temporarily',
          403 => 'Forbidden',
          404 => 'Not Found',
        ],
      ])
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'list_default',
        'weight' => 6,
      ])
      ->setDisplayOptions('form', [
        'type' => 'options_select',
        'weight' => 6,
      ])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE);

text, text_long, text_with_summary fields

These fields store a text with a text format.

As the default formatted, all of them uses text_default, for the widget – text_textfield, text_textarea and text_textarea_with_summary.

   $fields['text_long'] = BaseFieldDefinition::create('text_long')
      ->setLabel(t('Text (formatted, long)'))
      ->setDescription(t('Test formatted text.'))
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'text_default',
        'weight' => 6,
      ])
      ->setDisplayOptions('form', [
        'type' => 'text_textarea',
        'weight' => 6,
        'rows' => 6,
      ])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE);

datetime field

   $fields['start_date'] = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Only Date'))
      ->setDescription(t('Date field example.'))
      ->setRevisionable(TRUE)
      ->setSettings([
        'datetime_type' => 'date',
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'datetime_default',
        'settings' => [
          'format_type' => 'medium',
        ],
        'weight' => -9,
      ])
      ->setDisplayOptions('form', [
        'type' => 'datetime_default',
        'weight' => -9,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

The rest of the fields are pretty simple.

If you need information about the widget, formatted, or settings of these fields, try to find it in this directory – core/lib/Drupal/Core/Field/Plugin/Field/FieldType, or search in core directory files by "@FieldType(" keyword.

Please note, if you work with an already created entity type, you need to run a command for updating this entity. Also, this update will fail if you have any generated data in this entity.

With drush just run:

drush entity-updates -y

In hook_update_N you can apply changes with this code:

\Drupal::service('entity.definition_update_manager')->applyUpdates();

Please be aware that for Drupal 8.7.0, the support for automatic entity updates has been removed. Read more details here.

Check the important links now:

Igor
Team Lead and technology leader. Writes about Drupal, technologies and digital innovations.

LET'S CONNECT

Get a stunning website, integrate with your tools,
measure, optimize and focus on success!