Once you have created a field in Drupal, the fieldname will haunt you forever. A spelling mistake will keep living, and refactoring is out of the question.
It is however possible to change a fieldname in Drupal 6, but it might cost you a couple of hours work and a hard focus.
Drupal stores the fieldname in every thinkable place:
The obvious content-field-tables are an easy task, you can even do that manually. But Drupal also stores the fieldname in many other not-so-evident places, in views for example where fieldnames are stored as serialized data.
An all working script to change the fieldname is not evident (a reason why the possibility is not included by default in Drupal). There is a module that did an approach to change a fieldname, but in my option it’s best to do it all manually with a checklist.
Step by step guide
I made a step by step guide about how to change the machine name of a Drupal-6 field.
Backup your entire database. Test this script on your local machine or on a dev-server, not in a live environment. There is no guarantee that it won’t break your database.
2) Automatic script to change evident table names and column names
I made a php-script to make the task easier.
- changes the fieldname in the most common places in the database.
You’ll have to:
- edit the variables $old and $new (resp: old fieldname, desired new fieldname). Keep them lowercase and only use underscores.
- execute this script once (you could copy/paste it in index.php under the bootstrap call).
If it generates errors:
- it’s probably because a table doesn’t exist
- because you have a table prefix.
- you have a different database than MySQL.
db_query("ALTER TABLE content_field_%s CHANGE COLUMN field_%s_%s field_%s_%s %s;", $old, $old, $subfield_name, $new, $subfield_name, $column["Type"]);
//rename the table name of the field
echo "Rename table $old to $new";
db_query("RENAME TABLE content_field_%s TO content_field_%s", $old, $new);
// set the links between the content type and the fields correct
echo "Update table content_node_field";
db_query("UPDATE content_node_field SET field_name = 'field_%s' WHERE field_name = 'field_%s'", $new, $old);
echo "Update table content_node_field_instance";
db_query("UPDATE content_node_field_instance SET field_name = 'field_%s' WHERE field_name = 'field_%s'", $new, $old);
echo "update locales_source";
db_query("UPDATE locales_source SET location = REPLACE(location, 'field_%s', 'field_%s')", $old, $new);
db_query("UPDATE locales_source SET source = REPLACE(source, 'field_%s', 'field_%s')", $old, $new);
echo "update menu_links";
db_query("UPDATE menu_links SET link_path = REPLACE(link_path, 'field_%s', 'field_%s')", $old, $new);
db_query("UPDATE menu_links SET router_path = REPLACE(router_path, 'field_%s', 'field_%s')", $old, $new);
echo "update menu_router";
db_query("UPDATE menu_router SET path = REPLACE(path, 'field_%s', 'field_%s')", $old, $new);
db_query("UPDATE menu_router SET page_arguments = REPLACE(page_arguments, 'field_%s', 'field_%s')", $old, $new);
db_query("UPDATE menu_router SET tab_root = REPLACE(tab_root, 'field_%s', 'field_%s')", $old, $new);
echo "Truncate table cache_menu (or do this in the performance page in case you work with memcached)";
db_query("TRUNCATE TABLE cache_menu"); // clear menu cache (or do this in the PERFORMANCE page in case you work with memcached)
// db_query("TRUNCATE TABLE views_object_cache"); //uncomment if you have views cache installed
3) Search other tables
It is possible that you have installed modules that store the fieldname in different places. Use an sql-script to figure out where your fieldname is used elsewhere and change it everywhere. (do not update table views yet!)
For views, things are a bit more complicated than a simple query. A view also stores the field name (eg: “field_url”) in its code, but it saves it a serialized object. For each field the string-length is prepended (eg: s:9:”field_url”). If you would change that to s:9:”field_new_url” it would simply break because “field_new_url” is not 9 characters. This makes it impossible to solve with a simple query. (keep in mind that the fieldname could be part of a larger string).
Replacing the fieldname with a simple REPLACE-sql, would result in broken views with missing content fields.
There is one effective trick to alter all your views without going to them manually: with bulk export and import.
- export all your views with the module views_bulk_export
- the exported result is a copy of your view, presented as a big php array.
- search/replace this array with the old and new fieldname
- install the newly created module
- if you have used views_bulk_export before and made changes inbetween, it’s possible you have to revert the views to see the result.
- clear caches; et voila: all your views are changed to the new fieldname.
4) Your templates
Search your php-templates (esp. views-templates) for the fieldname and replace them with the new fieldnames. Also check other code, like custom modules, for the fieldname.
5) Check CSS.
It could be that you have a css rule that depends on the fieldname. Do a quick search through your css-file to make sure you don’t use the old fieldname somewhere.
6) Clear all the caches
With the Drupal interface. Clear Varnish/Boost/Memcached or others.