Introduction

Management of site settings has been a challenge ever since the early days of the Drupal project. What is managed as configuration is often difficult to differentiate from the content. General site information is not the same as taxonomy vocabularies, terms, menus, or blocks.

Earlier versions of Drupal store a variety of settings as variables which are managed with variable_get(), variable_set() and variable_del() functions.

Drupal 8 comes with a new configuration management system that unifies storage and retrieval of configuration data centrally. It provides a set of APIs that custom modules can leverage in the same way as the core.

The new system covers the following:

  1. Simple configuration (Config API) — Settings that require synchronization between different environments, e.g. site name, slogan, user account settings, etc.
  2. Local configuration (State API) — Settings that are more transient or subject to change and which should not be synchronized between environments. e.g. the last cron run, the timestamp for statistics, last update time, etc.
  3. Complex configuration (Configuration Entity API) — These are more complex things or entities that require manipulation in the manner of create, edit, and delete. For example, user roles, views, fields, filter formats, etc.

CLI Interaction

We are going to use DrupalConsole, and we recommend our Introduction to DrupalConsole article for an overview of this excellent CLI tool for Drupal 8.

Config API

Let us interact with our simple configuration settings by viewing them first:

drupal config:debug

Some settings are more complex than others. You can get quick access by debugging them by the name of their key. For example, system.site settings:

drupal config:debug system.site

You can change the value of the name key with drupal config:override <name> <key> <value> command:

drupal config:override system.site name "My Demo D8 Site"

After that, debug system.site settings to see the change.

State API

We can also interact with our local configuration similarly:

drupal state:debug

These settings are simpler than the configuration settings we saw earlier. Checking the maintenance mode of our site is easy:

drupal state:debug system.maintenance_mode

To take the site down, we use the familiar override command, drupal state:override <key> <value>.

drupal state:override system.maintenance_mode true

You can revert that by overriding it back to false.

Code Interaction

In code, you have full access to the APIs provided by the configuration management system.

Config API

There are two types of Config objects — a read-only instance (immutable) and a read/write one (mutable). They can both be retrieved directly from the service container:

$immutableConfig = \Drupal::service('config.factory')->get('system.site');
$mutableConfig = \Drupal::service('config.factory')->getEditable('system.site');

This gives access to all the settings under the system.site key, i.e. in the system.site.yml file. You can also retrieve any subkey, and the calls are chainable.

$name1 = $immutableConfig->get('name');
$name2 = \Drupal::service('config.factory')->get('system.site')->get('name');

To edit, call the set() method:

$mutableConfig->set('name', 'X-Team Drupal 8 Demo');
\Drupal::service('config.factory')->getEditable('system.site')->set('name', 'X-Team Drupal 8 Demo');

Finally, you can save the changes:

$mutableConfig->save();

If you recalled that the functions are chainable, you could have done this:

$mutableConfig->set('name', 'X-Team Drupal 8 Demo')->save();

While all this may be well and good, usually, you need configuration settings in classes, and the recommended way is through Dependency Injection. In your class, implement Drupal\Core\DependencyInjection\ContainerInjectionInterface interface and inject the container service. Then, you can do something like this:

$this->container->get('config.factory')->get('system.site');

Or, after injecting the config.factory service itself:

$this->configFactory->get('system.site');

State API

This is similar to Config API but simpler. To read, get the State object from the container and call the get method on it. The argument is the name of the key for the setting to be read.

$offline1 = \Drupal::state()->get('update.last_email_notification');
$offline2 = $this->container->get('state')->get('update.last_email_notification');

As you can see, this is also mutable and chainable. Remember that this is for storing volatile environment-specific data. It should not be part of the deployment process.

To edit, call the set() method:

\Drupal::state()->set('update.last_email_notification', REQUEST_TIME);

It gets written to the key_value table in the database:

select * from key_value where name = 'update.last_email_notification';
+------------+--------------------------------+---------------+
| collection | name                           | value         |
+------------+--------------------------------+---------------+
| state      | update.last_email_notification | i:1498205343; |
+------------+--------------------------------+---------------+

To delete:

\Drupal::state()->delete('update.last_email_notification');

Conclusion

In Drupal 8, information is classified into content, session, state, and configuration types. In this short article, we have looked at how to interact with configuration and state types.

Recommended reading

  1. Configuration API overview
  2. Simple Configuration API
  3. State API overview
  4. Step 4: Convert Drupal 7 Variables to Drupal 8 Configuration