Drupal - How to change the length of field settings?
Dylan Tack solution is the easiest, but personally I enjoy exploring the inner wards of Drupal's database to seen how things are managed down there.
So, assuming you have a text field which machine name is field_text of 10 characters you want to grow to 25:
- data will be stored in two tables: field_data_field_text and field_revision_field_text
- definition is stored in field_config for the storage data, and field_config_instance for each instance of this field (stuff like label).
Now let's do a little heart surgery.
Alter the data tables columns definitions:
ALTER TABLE `field_data_field_text` CHANGE `field_text_value` `field_text_value` VARCHAR( 25 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL; ALTER TABLE `field_revision_field_text` CHANGE `field_text_value` `field_text_value` VARCHAR( 25 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
Change the definition column, this one is very tricky because it's stored in a BLOB, but that's not something that will stop you for doing this.
- Dissect the guts of this BLOB thing:
SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) FROM `field_config` WHERE field_name = 'field_text';
- This will give you something like:
a:7:{s:12:"translatable";s:1:"1";s:12:"entity_types";a:0:{}s:8:"settings";a:2: {s:10:"max_length";s:2:"10";s:17:"field_permissions";a:5: //a lot more stuff...
This is a PHP serialized array, the interesting part is
s:10:"max_length";s:2:"10";
, this mean this array has a property namedmax_length
(which name is a 10 characters string - hence the "s") which value is 10 (which is a 2 characters long string). It's pretty easy, isn't it?Changing its value is as easy as replacing the
s:2:"10"
part bys:2:"25"
. Be careful: if your new value is longer in character length, you have to adapt the "s" part accordingly. For example putting 100 will bes:3:"100"
as 100 length is 3 characters.Let's put this new value back in the DB, don't forget to keep the whole string.
UPDATE `field_config` SET data = 'a:7:{...a:2:{s:10:"max_length";s:2:"25";...}' WHERE `field_name` = 'field_text'
- Flush your caches.
???
PROFIT!
By the way, PhpMyAdmin has some setting to allow direct modification of BLOB columns, but why go the easy way?
PS: This can also save your life when putting some PHP code in views and getting a WSOD because of an error in your code.
function mymodule_update_7100() {
$items = array();
_field_maxlength_fix('field_name');
return $items;
}
function _field_maxlength_fix($field_name, $maxlength = 255) {
_alter_field_table($field_name, $maxlength);
$data = _get_field_data($field_name);
$data = _fix_field_data($data, $maxlength);
_update_field_config($data, $field_name);
}
function _alter_field_table($field_name, $maxlength) {
db_query("ALTER TABLE field_data_".$field_name." CHANGE ".$field_name."_value ".$field_name."_value VARCHAR( ".$maxlength." ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
db_query("ALTER TABLE field_revision_".$field_name." CHANGE ".$field_name."_value ".$field_name."_value VARCHAR( ".$maxlength." ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
}
function _get_field_data($field_name) {
$qry = "SELECT data FROM field_config WHERE field_name = :field_name";
$result = db_query($qry, array(':field_name' => $field_name))->fetchObject();
return unserialize($result->data);
}
function _fix_field_data($data, $maxlength) {
$data['settings']['max_length'] = (string)$maxlength;
return serialize($data);
}
function _update_field_config($data, $field_name) {
$qry = "UPDATE field_config SET data = :data WHERE field_name = :field_name";
db_query($qry, array(':data' => $data, ':field_name' => $field_name));
}
This appears to be a limitation of the current text module. text_field_settings_form() has this comment: "@todo: If $has_data, add a validate handler that only allows max_length to increase.".
As a temporary workaround, you could comment out '#disabled' => $has_data
in modules/field/modules/text/text.module, around line 77.
I couldn't find an existing issue for this specific case, but you might mention it on #372330.