Skip to content

Instantly share code, notes, and snippets.

@fredysan
Last active October 26, 2023 20:43
Show Gist options
  • Save fredysan/afdd64525bede80c1e4957ac9030802a to your computer and use it in GitHub Desktop.
Save fredysan/afdd64525bede80c1e4957ac9030802a to your computer and use it in GitHub Desktop.
Drupal 9/10 Change type of fields with existing data
<?php
use \Drupal\field\Entity\FieldStorageConfig;
use \Drupal\field\Entity\FieldConfig;
function mymodule_update_9001() {
$database = \Drupal::database();
$table = 'node__field_name';
$entity_type = 'node';
$field_name = 'field_name';
$new_field_type = 'datetime_timezone';
// #1 Load storage configuration.
$field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);
// If storage config is not found, there is nothing to do.
if (is_null($field_storage)) {
return;
}
$rows = [];
// #2 Fetch the data for the old field.
if ($database->schema()->tableExists($table)) {
$rows = $database->select($table, 'n')
->fields('n')
->execute()
->fetchAll();
}
$new_fields = [];
// Use existing field config for new field.
foreach ($field_storage->getBundles() as $bundle => $label) {
$field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
$new_field = $field->toArray();
$new_field['field_type'] = $new_field_type;
$new_field['settings'] = [];
$new_fields[] = $new_field;
}
// #3 Take the old storage configuration present it as an array and update it's settings.
$new_field_storage = $field_storage->toArray();
$new_field_storage['type'] = $new_field_type;
// #4 Deleting field storage which will also delete bundles(fields).
$field_storage->delete();
// #5 Purge field data now to allow new field and field_storage with same name
// to be created. You may need to increase batch size.
field_purge_batch(100);
// #6 Create new field storage, create a new storage based on configuration above.
$new_field_storage = FieldStorageConfig::create($new_field_storage);
$new_field_storage->save();
// #7 Create new fields.
foreach ($new_fields as $new_field) {
$new_field = FieldConfig::create($new_field);
$new_field->save();
}
// #8 Restore existing data in the same table.
if (!empty($rows)) {
foreach ($rows as $row) {
$database->insert($table)
->fields((array) $row)
->execute();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment