The weather module's settings form can now save an API key and a default location. But a settings form that only ever writes is useless — somewhere else in the module, real code (a block, a controller) needs to actually read those values back out to call the weather API. This lesson is that other half: retrieving configuration programmatically, safely and efficiently.
What you'll learn in this lesson
- How to read a config value with
config.factoryfrom any service, controller, or block - Why you should always use the immutable
get()for reading, nevergetEditable() - How to read one key vs. the whole config object at once
- What happens when you read a key that was never set
Reading the weather module's API key
From inside a controller, service, or block plugin, reading a single value looks like this:
$api_key = \Drupal::config('weather_module.settings')->get('api_key');
if (empty($api_key)) {
// Handle the "not configured yet" case explicitly.
return ['#markup' => $this->t('Weather module is not configured yet.')];
}
\Drupal::config($name) is the procedural shortcut for the same config.factory service from the last lesson, just returning the immutable form — exactly what reading calls for. If you're inside a class that supports dependency injection (a controller, a service, a form), inject config.factory properly instead of calling the static \Drupal::config() helper, since it makes the dependency explicit and the class easier to unit test.
Reading one key vs. the whole object
// One specific value:
$location = \Drupal::config('weather_module.settings')->get('default_location');
// Every value in the config object, as an array:
$settings = \Drupal::config('weather_module.settings')->get();
Calling get() with no argument returns the entire config object's data as a nested array — handy when you need several related values at once, since it's one call instead of several. Calling it with a key does what you'd expect: returns just that value, or NULL if the key was never set.
NULL quietly — Drupal does not throw or warn. This is exactly why the previous lesson on default configuration matters: without a shipped default, get('api_key') on a freshly installed site returns NULL, and your code needs to handle that explicitly, as the example above does.Quick check: why does reading configuration always use
get()/\Drupal::config()rather thangetEditable(), even thoughgetEditable()would technically still return the right value? (Answer: the immutable object returned byget()can be safely cached and shared across the whole request without any risk of unrelated code mutating it mid-request — usinggetEditable()everywhere would quietly defeat that caching and invite bugs where one part of the code accidentally changes config another part relies on.)
Key takeaways
- Read configuration with the immutable
get()(or\Drupal::config()), nevergetEditable()— reserve the editable form for actually writing. get('key')returns one value orNULLif it was never set;get()with no argument returns the whole config object as an array.- A missing config key fails silently (returns
NULL) rather than throwing — always code defensively around values that might not be set yet. - Prefer dependency-injecting
config.factoryin classes that support it, over the static\Drupal::config()helper.
Coming up next
That NULL-on-a-fresh-install problem is exactly what the next lesson solves: shipping a default configuration file so the weather module works with sensible defaults the moment it's installed, before anyone ever visits the settings form.