The previous lesson ended with a real limitation: config/install/ only runs once, at install time. So what do you do six months later, when the weather module already has thousands of live installs and you need every one of them to gain a new units setting, or rename an existing key? You can't ask every site to reinstall the module. This is exactly the problem hook_update_N() exists to solve.
What you'll learn in this lesson
- What
hook_update_N()is and when Drupal actually runs it - The naming convention behind that mysterious
N - How to safely add a new key to already-active configuration
- Why update hooks must be idempotent-safe and never depend on module code that might change later
Adding a new setting to already-installed sites
Say the weather module needs a new units setting (metric or imperial) added to every site that already has it installed. That goes in weather_module.install:
/**
* Add a default 'units' setting to existing weather_module installs.
*/
function weather_module_update_10001() {
$config = \Drupal::configFactory()->getEditable('weather_module.settings');
if ($config->get('units') === NULL) {
$config->set('units', 'metric')->save();
}
}
The number after update_ is a version number you choose yourself — convention is a 4-digit number where the first digit tracks your module's own major release (10001, 10002, ...). Drupal keeps a per-module record of the highest update number that's already run on a given site, in the key_value table. Running drush updb executes every update function whose number is higher than what's already recorded, in ascending order, then bumps that stored number forward — so each one runs exactly once per site, ever.
Why the get('units') === NULL check matters
Update hooks need to be safe to re-run without corrupting anything, because a failed drush updb partway through is a real scenario a site administrator will eventually hit and re-run. Checking whether units is already set before overwriting it means running this function twice by accident doesn't clobber a value a site builder may have already changed in between.
\Drupal::configFactory() and \Drupal::database(), exactly as shown above.Quick check: a site already has
weather_module_update_10001()recorded as run. You add a newweather_module_update_10001()— reusing the same number — with different logic inside it. Will it run on that site? (Answer: no. Drupal tracks the highest number already executed per module; reusing a number that's already run means it will never fire again on sites that passed it. Always use a new, higher number for new update logic — never edit an update function that's already shipped.)
Key takeaways
hook_update_N()lets you change configuration (or run any one-time migration logic) on sites where your module is already installed —config/install/alone can't reach them.- The
Nis a version number you assign; Drupal runs every update function numbered higher than what's already recorded for that module, in order, exactly once. - Never reuse or edit an update number that's already shipped — always add a new, higher one for new logic.
- Guard update hooks against re-running destructively (check before overwriting), and avoid depending on your module's own higher-level code inside them.
Coming up next
That closes out configuration management — the weather module can now be configured, read from anywhere, ship with sensible defaults, and evolve safely on live sites. Next, we turn to Forms: building the actual settings form UI that lets a site builder set that api_key and default_location in the first place.