Environment Configuration for WordPress and Drupal

What is Multi-Stage Configuration?

When I first started web development, the idea of multi-stage configuration of websites was very foreign to me. What is it? According to Capistrano, the most popular Ruby Gem for application deployment, “[multi-stage] allows [one] to use a different deployment strategy for different scenarios.”  Basically, it allows you to have multiple configurations of your site based on environment type variables.

I was introduced to the concept while working on some legacy Rails 2.x applications; you would simply run cap staging deploy or cap production deploy, and it would automatically figure out where to send the code to, what databases to update, etc. I got pretty spoiled doing this, as it pretty much rendered production errors a non-issue; if a new feature I had been working on didn’t work, I’d find out in the staging environment before it hits the live site. It was quite a gem to have.

WordPress and Drupal

Well, as time wore on, we started to move away from doing custom Rails applications to using WordPress and Drupal. We still were doing staging/production sites, but without capistrano to work with, I had to manually remember to copy configurations, change settings, run migrations, etc. It was a nightmare. More times than I’d like to admit, I messed this up and left a staging site connected to the live site’s database – that was a mess!

I started to look for ways to solve the issue of having to remember to switch the settings when I moved stuff back and forth between production and staging sites. I found a couple of examples, before I settled on this basic one:

/**
 * @param null $stage local|staging|production
 *             Forces the specified stage to be loaded
 *
 * @return mixed
 */
function load_config( $stage = null ) {
  $env = "production";

  // local configuration checks by computer hostname
  // add your hostname here to detect local env
  if( in_array(gethostname(), ["ubuntu"]) ) {
    $env = "local";
  }

  // staging configuration is detected by server name, NOT http host
  // not as easily spoofed
  elseif( in_array($_SERVER['SERVER_NAME'], ["staging.example.com"]) ) {
    $env = "staging";
  }

  // force stage, if one is specified
  elseif( !empty($stage) ) {
    $env = $stage;
  }

  $file = __DIR__ . "/.env.{$env}.php";

  // make sure the file is readable / exists
  if( !is_readable($file) ) {
    throw new Exception( "Configuration File For {$env} Not Found!" );
  }
  return require_once $file;
}

// load the database configuration based on the site environment
$databases = load_config( getenv("SITE_ENV") );

I moved the sensitive settings into Unix-style hidden files, “.env.local.php“, “.env.staging.php“, and “.env.production.php“, and then loaded that based on the results of that function. By doing this, I didn’t have to rely on myself to remember to switch configurations, thus eliminating the possibility of forgetting to switch the connection settings.