January 9, 2015

Configuration cogs
This is the second in a series of posts about Drupal 8's configuration management system. The Configuration Management Initiative (CMI) was the first Drupal 8 initiative to be announced in 2011, and we've learned a lot during thousands of hours of work on the initiative since then. These posts will share what we've learned and provide background on the why and how. In case you missed it, you can read the first part here.

Careful what you put in your configuration keys

If you have dynamic configuration keys you need to ensure that they never contain a dot. This is a simple rule and implicit in the API almost since it was implemented. If you refer to a configuration key as page.403, then the configuration will have key named page which is an array with a key of 403. It sounds simple and easy to avoid, but it has proved anything but. 

Originally, the allowed values for an options field were stored as keys, which worked fine for everything apart from float values, for example, 3.14. The solution to the float value problem was to rearrange the array so the values were not used as keys. 

In fact, this points to a general rule. You need to be very careful when user input is used as a configuration key. For example, allowing dots in machine names is likely to lead to a lot of trouble, the reason it is never done in core.

Sites own their configuration, not modules

In Drupal 8, we have attempted to pay greater attention to data integrity and predictable behaviours. For example, in Drupal 7 default Views are provided in PHP code by implementing hook_views_default_views() in a module. If a default View is used by a site without any customisations, then its definition remains in code. If next version of the module has changes to its default View, then these changes are automatically implemented on the site when the site owner upgrades the module. Is this the correct behaviour? The original default View has delivered the required functionality for the site. It might have gone through QA and an acceptance testing process. Should the module author be able to make these changes to a site? Of course the module author should ensure that default Views provided by the module still work, but styles and text shouldn’t change and new displays should not be added. If the site owner had customised just one thing on the View, then it would have been moved to the database, and the module update would do nothing. Additionally, the revert button on the Views UI would not revert the View to the state it was in before the site owner customised it. Rather, it would revert to a completely new, never-seen-before (on that site) state.  These types of unpredictable behaviours are very confusing. 

Fortunately, Drupal 8 does not work this way. Modules provide default configuration in their config/install directory. When the module is installed, the default configuration is imported into the site's active configuration. All default configuration entities are assigned a universally unique identifier (UUID) during the install process. This enables the configuration system to discern the difference between a rename and a deletion/creation.

A site owns its active configuration, not the module that provides the default configuration. If a module changes a default configuration value from true to false, it should not just go and update the active configuration, since the website might rely on that value being false. Therefore knowing which config entities the module has provided is not actually that useful. If a module changes the structure of its configuration so that existing active configuration will no longer work, it will need to write a hook_update_N function to fix the active configuration.

Pro Tip: The easiest way to create a default configuration Entity is to create it through the user interface. For example, to provide a View in your module, create it through the Views UI, export the configuration to a YAML file and then copy it into your module's config/install directory. If you do this, you need to remember to remove the UUID key from the file.

Next Steps

If you've been inspired by this post and want to help get the configuration system finished for release, we have a few critical and major issues to fix. Don't hesitate to reach out to me in IRC if you want to work on any of them. My nick is alexpott.

Future posts in this series will cover configuration dependencies, schema and overrides.

This post has had input from: catch, mtift, susanmccormick, and xjm.