Ever found yourself in a situation where you needed to increase the length of a text field that already contains data in your Drupal site? Maybe you started with a shorter field length and now your content editors need more space.
It's a common scenario, but changing field lengths in production can be tricky, and it cannot be done via the user interface in the CMS. The only option is to update it using code.
Today, I'm sharing a reliable solution that lets you update text field lengths without losing any data. This approach handles both the database tables and Drupal's configuration, ensuring everything stays in sync.
Below is the code sample you can use to update the maximum length of a text field.
use Drupal\field\Entity\FieldStorageConfig;
/**
* Updates the length of a text field which already contains data.
*
* @param string $entity_type_id
* The entity type ID.
* @param string $field_name
* The field name to update.
* @param int $new_length
* The new maximum length for the field.
*/
function _change_text_field_max_length(string $entity_type_id, string $field_name, int $new_length): void {
$schema = \Drupal::database()->schema();
$table = $entity_type_id . '__' . $field_name;
$table_revision = $entity_type_id . '_revision__' . $field_name;
$new_field = [
'type' => 'varchar',
'length' => $new_length,
];
$col_name = $field_name . '_value';
try {
$schema->changeField($table, $col_name, $col_name, $new_field);
if ($schema->tableExists($table_revision)) {
$schema->changeField($table_revision, $col_name, $col_name, $new_field);
}
$storage_key = "$entity_type_id.field_schema_data.$field_name";
$storage_schema = \Drupal::keyValue('entity.storage_schema.sql');
$field_schema = $storage_schema->get($storage_key);
$field_schema[$table]['fields'][$col_name]['length'] = $new_length;
if ($schema->tableExists($table_revision)) {
$field_schema[$table_revision]['fields'][$col_name]['length'] = $new_length;
}
$storage_schema->set($storage_key, $field_schema);
\Drupal::configFactory()
->getEditable("field.storage.$entity_type_id.$field_name")
->set('settings.max_length', $new_length)
->save(TRUE);
FieldStorageConfig::loadByName($entity_type_id, $field_name)->save();
}
catch (\Exception $e) {
\Drupal::logger('system')->error(
'Failed to update field length for @entity_type.@field: @message',
[
'@entity_type' => $entity_type_id,
'@field' => $field_name,
'@message' => $e->getMessage(),
]
);
}
}
Here's the cool part - this solution takes care of:
- Both your main content and revision tables (because we all use revisions, right?)
- Updates the storage schema configuration
- Modifies the field configuration
- Includes error logging for when things don't go as planned
To use this in your own project, you can add it as an update hook in your custom module. For example, if you need to increase a "Additional Content" field to 1024 characters, it's as simple as:
function MY_MODULE_update_10001(): void {
_change_text_field_max_length('node', 'field_additional_content', 1024);
}
This simple update hook makes it easy to roll out the change across different environments, ensuring consistency in both your development and production setups.
The function works with any entity type and field, so it's pretty versatile. Just make sure to test it in a development environment first - while it's designed to be safe, it's always better to verify everything works as expected before running it on production.
Remember to clear your caches after running the update. While the function handles the heavy lifting, Drupal might need a quick refresh to pick up all the changes.
Updating field lengths in Drupal, especially when data already exists, can be challenging. However, with a careful approach that updates both the database schema and the field configuration, you can safely extend text fields without downtime or data loss.