1

I have the following datetime field definition for my content entity:

$fields['start_date'] = BaseFieldDefinition::create('datetime')
  ->setLabel(t('Start date'))
  ->setDescription(t('Start date in GMT time.'))
  ->setSettings([
    'default_value' => DrupalDateTime::createFromTimestamp(time()),
  ])
  ->setDisplayOptions('view', [
    'label' => 'above',
    'type' => 'string',
    'weight' => -4,
  ])
  ->setDisplayOptions('form', [
    'type' => 'datetime_default',
    'weight' => -3,
  ])
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE);

As a result, when creating a new entity, I get the field display without default value set in a form. I also tried setDefaultValue method but with no luck. What is the proper way to set the default values for the custom content entities?

6 Answers 6

8

You need to pass in a callback function that is evaluated when the entity is saved. If you evaluate the time value in YourEntity::baseFieldDefinitions, then the default value will fixed at whatever time the entity type was installed.

DrupalDateTime::createFromTimestamp can't serve as a callback because it expects you to pass a timestamp. The default value callback needs to take two arguments: the entity being saved and the field definition itself:

  • \Drupal\Core\Entity\FieldableEntityInterface $entity
  • \Drupal\Core\Field\FieldDefinitionInterface $definition

See the API docs: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Field%21FieldConfigInterface.php/function/FieldConfigInterface%3A%3AsetDefaultValueCallback/8.7.x

So you'll need to create a callback function, e.g.

use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;

// ...

function mymodule_get_current_datetime($entity, $definition) {
  $current_time = DrupalDateTime::createFromTimestamp(time());
  return $current_time->format(DateTimeItem::DATETIME_STORAGE_FORMAT);
}

And then pass that callback as a string.

$fields['start_date'] = BaseFieldDefinition::create('datetime')
  ->setLabel(t('Start date'))
  ->setDescription(t('Start date in GMT time.'))
  ->setDefaultValueCallback('mymodule_get_current_datetime')
  ->setDisplayOptions('view', [
    'label' => 'above',
    'type' => 'string',
    'weight' => -4,
  ])
  ->setDisplayOptions('form', [
    'type' => 'datetime_default',
    'weight' => -3,
    'default_value' => DrupalDateTime::createFromTimestamp(time()),
  ])
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE);
3

Field of type datetime accept date with format Y-m-d\TH:i:s So to set the default value, the date should be in this format, try with the following.

// Get the current date time in the format Y-m-d\TH:i:s.
    $current_date_time = DrupalDateTime::createFromTimestamp(time())
      ->format('Y-m-d\TH:i:s');
    $fields['start_date'] = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Start date'))
      ->setDescription(t('Start date in GMT time.'))
      ->setDefaultValue($current_date_time)
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'datetime_default',
        'weight' => -3,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);
1

To add current datetime when create or update your values you should use:

BaseFieldDefinition::create('created')
BaseFieldDefinition::create('changed')
1

You can pass an array to the default value to use the current time the entity is being created.

$fields['start_date'] = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Start date'))
      ->setDescription(t('Start date in GMT time.'))
      ->setDefaultValue([
        'default_date_type' => 'now',
        'default_date'      => 'now',
      ])
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'datetime_default',
        'weight' => -3,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

The key bit of information here being:

[
    'default_date_type' => 'now',
    'default_date'      => 'now',
]
1

Based on @berramou answer, I think this would be the right way (timezone and format wise):

->setDefaultValue(DrupalDateTime::createFromTimestamp(\Drupal::time()
      ->getRequestTime(), DateTimeItemInterface::STORAGE_TIMEZONE)
      ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT))
1
  • 1
    I don't think this will work as this code will just run at the time the module gets installed so will still be a static date. Your saving a string, not a dynamic function.
    – Felix Eve
    Commented Mar 29, 2021 at 8:18
0

In addition to the answer of CallMarl, mentioning that you should use another data type instead, the actual proper way to initialize any data of your custom entity, including not only timestamps but anything else, is to use the preCreate() function, for instance:

public static function preCreate(EntityStorageInterface $storage, array &$values) {
  parent::preCreate($storage, $values);

  $values['user_id'] = \Drupal::currentUser()->id();
  $values['created'] = time();
  $values['uuid'] = \Drupal::service('uuid')->generate();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.