Blair Wadman 7 minute read

Why you should not always use Drupal Features for settings, and what you can use instead

The Drupal Features module covers a lot of our needs with automating the deployment of database settings for Drupal 7. It allows you to export configuration to code and nicely wrap it up as a module. This means you easily deploy your changes to the live site (or a staging site) without having to repeat the configuration changes. It also means you can apply the changes to a different site.

If you are new to Features, check out my Drupal 7 Features tutorial.

But using Features is not always the best approach. Even if you can export something using Features, it doesn't mean you should.

An example

Consider the following: You have a setting in an admin form that you want to deploy to the live site. For example, the site name and slogan, which you can set in Administration > Configuration > System.

You can add that to a feature by using the Strongarm module. Strongarm allows you to add any Drupal variable to a feature. System settings like site name and slogan are stored as Drupal variables (if you would like to learn how to create your own admin form which stores variables like this, check out my post Create your first Drupal admin interface)

But what happens when the administrator wants to change the site name or slogan setting on the live site? The feature becomes overridden because the setting stored in the database on the live site no longer matches the setting stored in code in the feature.

At some point in the future, you do another deployment to the live site. You have updated the same feature again and you decide you need to revert the feature for its changes to take effect (it is generally good practice to do a features revert all on every deployment). At this stage, you are blissfully unaware that the administrator has changed a setting that happens to be stored in the feature you just re-deployed.

The site name and slogan setting change that the administrator made is gone. Nuked. Destroyed. Why? Because you just reverted the feature, which reverts any database settings that the feature controls and turns it back to the setting that is stored in code. You probably won't even realise that you have destroyed the administrators setting change because you fully intended to revert the feature.

You are going to end up with one unhappy administrator. Best case scenario? The administrator informs you so you can fix it. Worse case scenario? He/she doesn't notice and you have a bug. The middle case scenario is that he/she changes it back but doesn't tell you. You then do another deployment in the future and it gets reverted again. The administrator thinks it is a weird glitch in the matrix and changes it again. This song and dance can carry on for quite a while before the administrator mentions it to you. I have seen this happen a lot.

The Solution

Right, so we know the problem. How do we solve it?

Simple: Don't export settings in a feature if you fully intend for it to be changed on live.

Now I am sure you are thinking that it means going back to the old school way of manually updating the live site with the setting when you first do the deployment. Not the case. The goal is to still do as much in code as possible without having to manually make manual configuration changes to the live site.

To set an admin setting during deployment, you just need to use the variable_set() function in a deployment module.

Create a site deployment module

Create your module with these three files:

site_deployment.info
site_deployment.module
site_deployment.install

The info file

The info file should contain the following:

name = Site Deployment
description = Deployment module, used to automated changes to this site
core = 7.x
version = "7.x-1.x-dev"

The module file

The module file doesn’t need to contain any working code. We will simply include a comment.

<?php
/**
 * @file
 * Module file for Site Deployment
 */

The install file

In the install function, you can write an implementation of hook_update_N for each deployment. This is the heart of the site deployment module.

Let’s take a look at the code for the first function.

<?php
/**
 * @file
 * Install file for Deploy Update
 */

/**
 * Deployment function for 1st deployment
 */
function site_deployment_update_7000() {
  variable_set(variable name, variable value);
}

This sets the variable for the setting that the administrator is likely to change on the live site. For this to take effect, you just need to deploy site_deployment to the live site and run update.php

In our example, we want to set the site name and site slogan. This will achieve our goal of automatically deploying changes with code and still allow it to be edited on the live site.

To do that, we just need to add two variable sets to an update function in the site deployment module. The first one sets the site name and the second the site slogan.

/**
 * Set the site name and slogan.
 */
function site_deployment_update_7000() {
  variable_set('site_name', 'Wonderful website');
  variable_set('site_slogan', 'A wonderful website about Drupal');
}

Finding the variable name

The variable name for the site name is site_name and for the site slogan is site_slogan. You might be wondering, how do you find the variable name and value for another variable?

There are a couple of ways

  1. When you look at the admin form, view source (or inspect the element). The html name attribute is the name of the variable
  2. Look in the variable table in the database. This will show you all of the variables that are saved to the database.
  3. Use the variable editor that comes with the Devel module.
  4. Use the Drush vget command. Get a list of all current variables and their values with drush vget. Or find variables from specific modules by using piping the output to grep. E.g. find variables from pathauto: drush vget | grep pathauto. [Thanks David for suggesting this in the comments.]

Once you get used to writing update hooks with variable_set() it becomes second nature. Even when I am updating a setting on my local environment, I normally write the variable_set(). This is the full process:

  1. Test out the setting change the traditional way, by clicking it on the form
  2. Once you are happy with what you have, change it back.
  3. Create a new update hook in your deployment modules install file.
  4. Run update.php (or drush up) on your local environment. Check the setting and make sure it has changed
  5. Deploy your deployment module to your development server, or whichever server is next in line (it could be straight to QA or Staging). Run update.php there. Now the client, reviewer etc can view the change and sign it off (or not). You now safely know that you don't have to remember to manually make this change on the live site at some future date when it is supposed to go live. You just deploy the deployment module and run update.php and you're done.

Wrapping up

Using code to store and deploy database settings is a wonderful thing but the Features module is not the right hammer for every nail. Setting variables in a deployment module is one of the quickest ways to get started with using a deployment module and it solves the problem of a feature becoming overridden when settings are changed on a live site.