Entity baseFieldDefinitions fields examples in Drupal 8

Nov 14, 2019
By Ihor
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:

    Ihor
    Developer with 8 years of experience in developing web applications. His extensive expertise in web application integration with third-party services allowed him to succeed working on e-commerce projects, sites for startups, sites for Medicine & Health companies.

    LET'S CONNECT

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