A look back at Drupal 7
Configuration Management in Drupal 7 isn't as simple as its equivalent in Drupal 8. In Drupal 7, almost the entire configuration set on a site is stored in the database by default. This includes simple variables, content types and field configuration, settings from custom or contributed modules, and so on.
Using the database to store settings makes it really hard to track configuration changes or roll back a bunch of settings to a state defined earlier.
Unfortunately, there is no real standard for Configuration Management in Drupal 7, but there are several ways to manage site and module settings in the code.
We will take a short look at the following five different approaches:
- Manual Configuration Management
- The
hook_install()
/hook_update_N()
function - The Features module
- The Configuration Management module
- Storing configuration variables in
settings.php
Manual Configuration Management
Many users of Drupal manage their configuration manually. They try to remember each setting they've made in the local development environment and then recreate every step on the live site. At first sight, this seems to be very fast and easy, but if you have to manually set permissions for some roles multiple times, you'll never want to do this manually again after hearing there are much better ways.
Additionally, you will never know if a setting has changed and all of your configuration will not be version-controlled (because it only exists in the database). Also, it makes working in a team much more painful than necessary.
If you ever want to share configuration between two or more instances of a site, don't do this.
Tip
Don't use manual Configuration Management!
The hook_install()/hook_update_N() function
Install and update hooks are the simplest way to manage configuration on a Drupal 7 site in code. The basic idea behind this approach is to set configuration values while installing a module or running update.php
. Within the .install
file of a custom module, you implement hook_install()
and/or hook_update_N()
, and add the code needed to set the configuration to these functions:
<?php /** * Implements hook_install(). */ function my_module_install() { // Set site name. variable_set('site_name', 'Configuration Management'); }
In this example, we simply set the variable site_name
to the Configuration Management
value, so the name of our site will be updated to this value after enabling the module. The possibilities given here are nearly endless. In addition to setting simple variables, you might add new roles, update block settings, or even create new content types. However, while it's technically possible, it is not recommended and not very simple to export complex configuration (think of fields or views). Also, you need a developer to actually write the code.
Unfortunately, this is one-way configuration management, so there is no way to automatically save changes that you have made on the site's configuration back to code. You have to update the code manually with the new settings (for example, add a new implementation of hook_update_N()
).
Additionally, you do not have any chance to see which settings were changed by a user. If you want to save the current state of configuration, you need to go through all settings set in hook_install()
or hook_update_N()
and compare them with the current settings on the site.
The Features module
To manage configuration in Drupal 7, most people use the Features module (https://drupal.org/project/features). If you need a simple tool to export your configuration and put it under version control, Features is the module to work with in Drupal 7.
What is the Features module?
To quote James Sansbury from Lullabot:
"The Features module is a module that creates other modules called features."
In other words, Features helps you to put your site's configuration into code so that you can keep track of changes and simply share it with other sites. It was originally created to serve another purpose: to group multiple configurations for one use-case so you could package actual site features and use them in different sites. However, due to a lack of alternatives, it ended up becoming popular as a tool to manage Drupal configuration.
Features works by using so-called components that hold information about configuration objects provided by Drupal itself or contributed modules.
Features uses different types of components: configuration objects that live in code without the need for an instance in the database (exportable components) and so-called faux-exportable components that must exist in the database. Exports of faux-exportable components are used to synchronize configuration objects in the database, so the settings are always up-to-date.
To make an object exportable, you can write a module and use your own default hook handling and export generation. The default hook provides a default state of your configuration object that is directly used on the site or synchronized with the database (depending on the needs of this object).
A very simple example of an object exported using a default hook is a content type. Custom modules can provide their own content types using hook_node_info()
:
<?php /** * Implements hook_node_info(). */ function cm_blog_node_info() { return array( 'blog' => array( 'name' => t('Blog'), 'base' => 'blog', 'description' =>t('Use for multi-user blogs.'), ), ); } ?>
This simple example (taken from api.drupal.org) defines a new content type with the machine name blog. Additionally, it sets the human-readable name to Blog and adds a short description to the type, so users know about its purpose.
A better way to make custom configuration objects exportable is to integrate the module with the CTools Export
API.
Note
The CTools Export
API has been designed to provide a standardized way to export and import objects in Drupal. Developers simply add some special keys to the object's schema and implement a load function as well as a save function.
Using the CTools Export
API, Features will automatically integrate with your module and handle the export and synchronization of your components. Prominent representatives of contributed modules that implement this in Drupal 7 are Views and Panels.
Creating a Feature
Creating a Feature is very easy. Using the user interface of the Features module, you simply add the components you would like to export to the newly created module. While generating the new module, Features uses the defined default hooks or the CTools Export
API to save the information about the components to code so you don't need to write the code yourself. While writing the code may be fairly easy for content types (as shown previously), writing down the complete configuration of a field, an image style, or even a view is not so simple, and you do not want to do this manually. With Features, you only need a few clicks to get the configuration into code. Take a look at the following screenshot:
In the preceding example, we selected the content type Blog along with some permissions. As you can see, Features automatically added the required dependencies to other modules along with the information about the fields of the content type and common variables related to the type.
After adding everything you want to include in the export, you can download the feature or let Features directly create the files on your disk.
Note
If you create a new Feature, make sure you use a unique machine-readable name that does not conflict with any existing module. The best practice is to prepend the machine name with an abbreviation of your project or site name (in our example, cm_blog
).
After downloading the Feature and enabling it in the same way as any other module, you are able to track changes to components in the Feature. For example, if you change the label of a field included in the Feature, the Feature will be shown as overridden. With the help of the Diff
module, it even displays each modified component as follows:
You can then choose between reverting the Feature to its default state (that's what you have in the code of your Feature), which would undo the change you made to your field label, or you can update the Feature, which gives you the modified values in code, so you can share it with others or distribute it to another environment.
Both tasks can either be done using the Feature UI or Drush, which is much faster.
The settings to export with Features
Basically, all components that rely on the CTools Export
API, or on modules that define default hooks, may be exported.
These include the following:
- Variables: These are exported using the Strongarm module, which implements the
CTools Export
API for all entries in thevariables
table of Drupal - Views: These are exported using the default hook:
hook_views_default_views()
- Content types: These are directly exported by the Features API using Drupal's
hook_node_info()
- Field definitions: These are exported using default hooks defined by Features itself
- And many more: These include text formats, image styles, and rules (http://www.drupal.org/project/rules)
The settings to not export with Features
While some components may theoretically be exportable, it is not always sensible to do this. For example, exporting cache variables or variables that store timestamps such as cron_last
, which stores the date when the last cron was run, would result in constantly overridden Features. There is also no benefit in having components such as this in code, because you can't actively change it, and you don't need to know its value for anything.
As a general rule of thumb, you should never export components that change often, such as timestamps or status variables.
The Configuration Management module
The Configuration Management module is the latest approach we will take a look at here. While Features was never really intended to do real Configuration Management, the Configuration Management module takes some core concepts from the Drupal 8 Configuration Management Initiative and makes them available for Drupal 7.
The main concept behind this module is the data storage architecture. It defines an activestore and a datastore to manage the configuration of a site. The activestore represents the current state of an individual configuration component (for example, a variable in the database) whereas the datastore is defined as the file that contains the default state of the component.
After changing the value of a component tracked by the Configuration Management module, you can save its value back to the datastore (the module updates the corresponding files for you) so that you can track the changes in your version control system.
Looking at the export of this configuration in the following screenshot, you will notice many similarities. This is due to the fact that both modules use the CTools Export
API and nearly the same default hooks to import/export the data.
The main advantage of the Configuration Management module in comparison to Features is the reduction to pure Configuration Management. There is no possibility for a developer to extend the export with custom code (that is hook_form_alter()
or hook_menu()
) as is done often when exporting configuration objects with Features. The export simply contains the components you want to put under version control and nothing more.
Storing configuration variables in settings.php
There is one more way to store settings back in Drupal 7: your site's settings.php, which you know from storing your database details in it. The Drupal installation process and Drupal modules use the variables
table to store different types of information that will be used at runtime. The values of these variables can be overridden in the settings.php
file. Every module, when enabled, may add variables that can be altered in the configuration setting. One example is the variable named theme_default
, which sets the default theme.
Variables stored inside your settings.php
file's $conf
array will override whatever is in the variables table of your database. This is really useful when you need different configuration for different environments, such as local, staging, and production.
There is a complete list of default variables available on a fresh installation of Drupal at https://www.drupal.org/node/1525472.