Retrieving Configuration Data in buildForm()for Drupal 8 , 9 , 10 , and 11

Last updated :  

A settings form that always opens blank is broken in a subtle way — visitors can't tell what's currently configured versus what they're about to change. Retrieving configuration data is what makes a form reflect reality: read the saved value inside buildForm(), before the form is even rendered, and hand it to the element as its #default_value.

What you'll learn in this lesson

  • Where to read config from — always inside buildForm(), before the elements are defined
  • The difference between loading config as read-only versus editable
  • How #default_value connects a stored setting to a rendered form field
  • What happens the first time a form loads, before any value has ever been saved

Retrieving config inside buildForm()

/**
 * {@inheritdoc}
 */
public function buildForm(array $form, FormStateInterface $form_state) {
  $config = $this->config('config_simple_example.settings');

  $form['message'] = [
    '#type' => 'textarea',
    '#title' => $this->t('Message'),
    '#default_value' => $config->get('message'),
  ];

  return parent::buildForm($form, $form_state);
}

How it works

Loading config read-only vs. editable

$this->config('config_simple_example.settings') inside buildForm() loads the config object in its normal, cached, read-only mode — appropriate here, since you're only displaying a value, not changing it. This is the same call used in submitForm(), but there it's implicitly editable because a subsequent set() is about to be chained onto it. Reading and writing use the identical entry point; the difference is only in what you do with the object afterward.

get('message') — reading one key

$config->get('message')

get() reads exactly one key from the config object and returns its current value, cast to whatever type the schema declared (recall from the schema lesson: message is typed text). You can call get() with no argument at all to retrieve the entire config object as an array, useful when a form needs to read several keys at once.

Connecting the value to the form via #default_value

$form['message'] = [
  '#type' => 'textarea',
  '#default_value' => $config->get('message'),
];

#default_value is the standard Form API property that pre-fills any element with a starting value — nothing config-specific about the property itself. What makes this a "config form pattern" is simply that the value being fed into it came from $config->get() rather than a hardcoded default or a database query.

What happens before anything's ever been saved? The very first time this form loads on a fresh install, get('message') returns whatever config/install/config_simple_example.settings.yml shipped as the default — 'Awesome settings' in this real example. That's exactly why every module with a config form should also ship a matching config/install/*.yml file: without one, the form's first load shows an empty field instead of a sensible starting value.

Quick check: why does buildForm() call $this->config() again, instead of reusing whatever submitForm() loaded on a previous request? (Answer: each HTTP request is stateless and starts fresh — buildForm() runs on every page load of the form, including the very first one, so it always re-reads from the actual saved config rather than relying on some value carried over from a different request.)

Key takeaways

  • Read config for display inside buildForm(), using the same $this->config($name) helper as the write side.
  • get('key') returns one typed value; get() with no argument returns the whole config object as an array.
  • #default_value is the standard Form API bridge between a saved config value and a rendered element — no special config-only property exists.
  • Always ship a matching config/install/*.yml file so a fresh install's form shows a sensible default rather than an empty field.

Coming up next

Reading and writing config safely also means rejecting bad input before it's ever saved — the next lesson, "Validating Configuration Forms," covers exactly that.