Drupal - Add new field to custom content entity type
After installation, you need to handle updating the schema yourself. There are some different scenarios, some are more easy to deal with than others. The most complex is moving data from one field type to another which means you would have to do a migration of data.
Anyways Drupal core has the entityDefinitionUpdateManager()
which can be accessed doing \Drupal::entityDefinitionUpdateManager()
. This manager can do a lot of the things you need to do when you change the base fields of content entities.
Creation of a new field is pretty easy, and all you need to make your own update hook:
function hook_update_8xxx() {
\Drupal::entityDefinitionUpdateManager()->applyUpdates();
}
This will apply all updates to all entities. This can generally be used for most things, but if there are data in Drupal has a failsafe that throws an exception to make sure it doesn't accidentally mess data up. During the beta the system attempted to handle data migration as well, but it didn't work well so it was decided that this is something module maintainers should do themselves.
As described in Write update functions for entity schema updates, automation removed (created on August 2015), which describes a change introduced on the 8.0.x branch, if you need to update the database schema used for an entity, you need to also implement hook_update_N()
with code similar to the following one.
Since the class implementing the entity is Course
, I assume the module machine name is course. Change the update number to the correct one for your module.
use Drupal\Core\StringTranslation\TranslatableMarkup;
function course_update_8110() {
$storage_definition = BaseFieldDefinition::create("string")
->setLabel(new TranslatableMarkup("Place"))
->setDescription(new TranslatableMarkup("The place of the course"))
->setSettings(["max_length" => 255, "text_processing" => 0])
->setDefaultValue("")
->setDisplayOptions("view", ["label" => "above", "type" => "string", "weigth" => -3])
->setDisplayOptions("form", ["type" => "string_textfield", "weigth" => -3]);
\Drupal::entityDefinitionUpdateManager()
->installFieldStorageDefinition('place', 'course', 'course', $storage_definition);
}
I also fixed a typo in your code: Instead of "weight"
, you wrote "wegith"
.
The code I am showing is for adding a new field. The change record I linked shows also the code to use when existing fields are promoted to entity keys,or when the cardinality of a field with existing data is changed from single to multiple (or from multiple to single).
Before Automatic entity updates can fail when there is existing content, leaving the site's schema in an unpredictable state (one of the issues linked from the change record) was fixed, update.php had an automated system to fix the entity schema, which didn't make the entity schema state predictable for module updates.
Given the branch that removed the automatic updates, I would say that practically all the modules need to use code similar to the one I show in this answer.
Starting from Drupal 8.7.0 you need to use the Update API for that task, like so:
In modulename.install
add a function like this:
function modulename_update_8001() {
$field_storage_definition = BaseFieldDefinition::create('timestamp')
->setLabel(t('Start'))
->setDescription(t('The first day'))
->setRevisionable(FALSE);
\Drupal::entityDefinitionUpdateManager()
->installFieldStorageDefinition('start', $entity_type_id, $entity_type_id, $field_storage_definition);
}
Then run drush updatedb
or go to Database Updates on the status report.
See https://www.drupal.org/node/3034742 for deeper understanding.