How to change the machine name of a content field in Drupal6 - developed.be

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.

Background

Drupal stores the fieldname in every thinkable place:

  • column-names
  • table-names
  • row-values

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.

1) Backup

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.

The script:

  • 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.

<?php
$old = "emailaddresss"; //old name of the field. Change this!
$new = "emailaddress"; //new name of the field. Change this!
 
//get the column names of the content field
$result_columns = db_query("SHOW FULL COLUMNS FROM content_field_%s", $old);
 
//rename the subfields (columns of content_field_$old)
while($column = db_fetch_array($result_columns)){
    echo("checking column" . $column["Field"]);
    if($column["Field"] != "nid" && $column["Field"] != "vid"){
        $subfield_name = substr($column["Field"], strlen("field_" . $old . "_"));
        echo "Alter subfield <b>$subfield_name</b>";
        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 <b>$old</b> to <b>$new</b>";
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
 
die("all done");
 
?>

 

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!)

3) Views

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.

  1. export all your views with the module views_bulk_export
  2. the exported result is a copy of your view, presented as a big php array.
  3. search/replace this array with the old and new fieldname
  4. install the newly created module
  5. 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.
  6. 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.

7) It should be finished. Perform a smoke test to see if it works.


Rss Comments

Comments

No comments yet.

Leave a comment