From $conf to $config and $settings in Drupal 8

With Drupal 7 we were used to leverage $conf to set variable overrides. Unfortunately this was sub-optimal. The Configuration override system documentation page says it best:

A big drawback of that system was that the overrides crept into actual configuration. When a configuration form that contained overridden values was saved, the conditional override got into the actual configuration storage.

Using $conf on Drupal 7

Let's say you wish to query the {variable} table for the site name.

mysql> SELECT name,value FROM variable WHERE name = 'site_name';
+-----------+----------------------+
| name      | value                |
+-----------+----------------------+
| site_name | s:12:"My site name"; |
+-----------+----------------------+
1 row in set (0.00 sec)

You can quickly get the information you want and confirm this is indeed the value your site returns at /admin/config/system/site-information. Now, if you want to override the entry in code, you can put the below variable override in settings.php.

// Override the site name.
$conf['site_name'] = 'My new site name';

When bootstrapping, Drupal would return the overridden site name with the original value left untouched in the database. Easy. Doing so also means the value provided in code wouldn't be modifiable from the Drupal administration interface any longer. Well, you could modify it, but it'd be overridden no matter what.

In Drupal 8 the variable subsystem is gone and we now need to leverage either $config or $settings depending upon what we wish to achieve. Both are being set via Settings::Initialize - Let's explore each to understand the differences.

When to use $config in Drupal 8?

$config is brought to you by the Configuration Management system. To keep it really simple, think about variable overrides and call them configuration overrides instead. And as you can see below, there are indeed similarities:

  • You can globally override specific configuration values for the site.
  • Any values you provide in these variable overrides will not be viewable from the Drupal administration interface. (Don't think that makes sense? There's an issue for that.)

But there are also notable differences. One I think worth mentioning is related to modules. In Drupal 7, it was easy to disable a module via $conf, by setting the below variable override.

$conf['page_load_progress'] = 0;

This was useful when - for instance - willing to have certain modules disabled in non-prod environments.

In Drupal 8 though, overriding the list of installed modules in core.extension is not supported as module install or uninstall has not occurred and modules cannot be disabled anymore. There is a contrib module to try and bring back this functionality to Drupal 8, but be careful of unintended consequences on a production site.

There are other particular configuration values that are risky to override, like field storage configuration which could lead to data loss. So, really, you have to make sure what is going to be overridden wouldn't have a negative impact on your site.

In any case, the administration interface displays the values stored in configuration so that you can stage changes to other environments that don't have the overrides. If you do want to see the overrides, then there's the Drush --include-overridden argument to do just that.

Let's say we wish to override the site name via settings.php.

$config['system.site']['name'] = 'My new site name';

To see the default and overridden values with Drush, just type the following.

// Default value
$ drush @site.env config-get system.site name
'system.site:name': 'My site name'
// Overridden value
$ drush @drucker.local config-get system.site name --include-overridden
'system.site:name': 'My new site name'

Or you can use the Drupal API directly.

// Default value
>>> $site_name = \Drupal::config('system.site')->getOriginal('name', FALSE);
=> "My site name"
// Overridden value
>>> $site_name = \Drupal::config('system.site')->get('name', FALSE);
=> "My new site name"

When to use $settings in Drupal 8?

Let's try to understand the difference with $config. It's clearly explained in \Drupal\Core\Site\Settings

Settings should be used over configuration for read-only, possibly low bootstrap configuration that is environment specific.

settings.php tries to clarify that even more.

$settings contains environment-specific configuration, such as the files directory and reverse proxy address, and temporary configuration, such as security overrides.

In other words, this refers to settings that wouldn't exist in the Configuration Management system. Here's an example. When defining the private path, you don't have a choice but to define it via settings.php.

$settings['file_private_path'] = '/mnt/private/files';

Another example is API keys. You certainly don't want those or other sensitive information to be stored in the configuration and exported in YAML files and/or tracked under version control.

Here's another example with Drupal's hash_salt that we're querying directly via Psy Shell:

Psy Shell v0.8.0 (PHP 7.0.14-1~dotdeb+8.1 — cli) by Justin Hileman
>>> \Drupal\Core\Site\Settings::get('hash_salt');
=> "MN7epuJ_8qcG5edFhe2-cg6x7evJQf_-DVrH4d3t6gAKH9tcDs5WtRoy814ukhLJLwEJaXuzQd"
```

Hopefully that clarifies the difference between `$config` and `$settings`. Let me know how you work with them and if I missed anything.

Aurelien Navarre

Senior Technical Solutions Analyst @Acquia - Drupalist by day, DevOps by night.

Lyon, France