Using hook_update_n() for non-database-related updates
Note that this article applies primarily to Drupal 6. When developing features or other modules, I often find myself making changes to the module dependencies or other aspects after my module has first been moved to the staging site. I use hook_update_N() for that. Here's how.
Initial install hook
Features normally don't do anything to the database, so typically we wont have an implementation of hook_install(), but we can still do stuff like add URL aliases using the install hook.
<?php
function myfeature_install() {
path_set_alias('path-in-english', 'path-in-french', NULL, 'fr');
}
?>Let's say we now deploy our feature to our staging site.
Using the update hook
At this point we want to add some more paths. We can't simply add them to the install hook implementation, because it will not be called on sites where myfeature is already installed. Rather, we need to define an update_N hook. Normally, one would use the update_N() hook to perform database-related updates to a module, and that's amply documented: just return whatever your database function returns.
We can also use the update hook to perform non-database-related operations. Two examples are: adding dependencies and adding more path aliases.
The return value of hook_update_N
When we're performing database-related operations, we call a database function and return its return value. Just look at any update hook implementation in any drupal core or contrib module.
If we are not calling any database function, here is what we need to return in an update_N() function:
<?php
function myfeature_update_6001() {
// do something that has nothing to do with the database, for example
// adding info programmatically or installing modules
if (!$error) {
return array(
array('success' => TRUE, 'query' => 'First message'),
array('success' => TRUE, 'query' => 'Second message'),
);
} else {
return array(
'[#abort]' => array(
'success' => FALSE,
'query' => 'say what went wrong',
),
);
}
}
?>Adding dependencies
Let's give an example with adding dependencies to your module after its initial launch. If you just add them to the .info file, they won't be recognized on later updates. For example:
- Create your module with dependency x in your module's .info file.
- Deploy your module on the site example.com.
- In a later version of your module, add dependency y to the module's .info file.
- Push it to example.com, and your module will crash if the module y is not active.
hook_update_N() can be used to ease the update. Simply define the following function, using the normal naming schema:
<?php
function myfeature_update_6001() {
$modules = array('module_x', 'module_y'); // you must also put these modules in your .info file as dependencies.
drupal_install_modules($modules); // note that this is for Drupal 6
foreach ($modules as $module) {
if (!module_exists($module)) {
return array(
'[#abort]' => array(
'success' => FALSE,
'query' => 'on or more of the modules ' . implode(', ', $modules) . ' can\'t be found. Please make sure they are installed.',
),
);
}
}
return array(
array('success' => TRUE, 'query' => 'The modules ' . implode(', ', $modules) . ' have been installed.'),
);
}
?>Adding paths
The same principle can be used to add paths:
<?php
function myfeature_update_6002() {
path_set_alias('second-path-in-english', 'second-path-in-french', NULL, 'fr');
return array(
array('success' => TRUE, 'query' => 'Added french path alias for second-path-in-english'),
);
}
?>Make sure to modify your install function as well
Note, though, that if you reinstall this module on a new Drupal site, update functions are not called. This is fine if your update function simply enables modules that are also in your .info file: the modules will be installed by Drupal's module installer so the update function does not need to be called. However, if we are adding new paths, we need to add them also in our install function.
<?php
function myfeature_install() {
path_set_alias('path-in-english', 'path-in-french', NULL, 'fr');
// do not call myfeature_update_6001 because it just adds depedencies
myfeature_update_6002(); // this must be called or else the second path alias won't be added to new installations of this module.
}
?>Push your latest version to example.com and update your database
At this point you can push version 2 of your feature to example.com, then visit example.com/update.php and run through the database update script.