Drupal update hooks in a multi developer environment
Mike Dixon
With large Drupal projects, especially those in their post-live phase, good code and release managment becomes vital.
Update hooks provide the mechanism by which database changes can be scripted and deployed to the live server, this article assumes you are already well versed with the ways of update hooks.
The two main problems we have with update hooks occur on multi developer projects
Same function is implemented in 2 branches. Imagine the situation where you have 2 seperate branches open on the same project, with different developers working on each branch.
Both branches want to update the module crm_integration so they both add the next available update hook crm_integration_update_6003.
This obviously isn't a problem during the testing phase, but as soon as you integrate the two branches you end up with 2 implementations of the same function and consequently a PHP error.
Two developers change the same update function This is possibly a more likely scenario, 2 developers working on the same branch both make changes to the same update function.
SVN will normally do a reasonable job of coping with this by merging the changes together, but occasionally it doesn't go so well and your left with
a bit of jiggery pokery to get thing back on track.
The solution
The solution is actually pretty simple, we use a simple helper function to scan a directory called update_X and include all the .inc files contained in it.
Every update function implemented is essentially just a stub which calls the helper function, with the actual grunt work of the update being done via .inc files.
This means that so long as our 2 developers do not add .inc files with the same name we never have a problem with code clashes.
It also has the added advantage of creating a bunch of nice re-usable include files that you can potentially pick up and re-use on different projects.
Enough with the waffle. Show me some code
First the helper function, dead simple just loops through the update directory and includes everything it finds:
function _CM_update_profile( $module_name, $version_number = 0){
$ret = array();
$directory = drupal_get_path('module', $module_name). '/update_'.$version_number;
$files = file_scan_directory($directory, '.inc');
foreach ($files as $absolute => $file) {
require $absolute;
}
$ret['#finished'] = 1;
return $ret;
}
Then each update function simple becomes
function my_module_update_6001(){
_CM_update_profile('my_module',6001);
}
function my_module_update_6002(){
_CM_update_profile('my_module',6002);
}
Simply add a directory called update_6001 (change the number to match your update), and then add your .inc files to that. We tend to include a ticket/bug reference on each include file just to help keep track
Hope someone finds this useful