Handling config files for local development, staging and production in PHP

I’ve had a few stabs at this and never been particularly happy with how it works. My last move was to only provide a skeleton config file under versioning, then complete variables like DB user and pass on individual servers.

Mostly this only had to be done once, but adding anything to the config file meant having to edit all of the individual config files on each server. And we use the same code base, with slight config changes, over about 12 different servers. I’ve used $_SERVER[‘HTTP_HOST’] as switch on some WordPress plugins and that does the job, but I didn’t like that it is possible to spoof headers.

	protected function getApiUrl() {
		if (!isset($this->apiUrl)) {
			if (strpos($_SERVER['HTTP_HOST'], 'local') !== false) {
				// Local test server
				$this->apiUrl = "http://local.XXXXX.com/api/";
			} else if (strpos($_SERVER['HTTP_HOST'], 'wmtest') !== false) {
				// Staging server
				$this->apiUrl = "http://dev.XXXXX.com/api/";
			} else {
				// Production server
				$this->apiUrl = "http://plugins.XXXXX.com/api/";
			}
		}
		return $this->apiUrl;
	}

I saw a recommendation to just drop a control file on each server with a simple, minimal set of definitions, then code the switch around that. This appealed, so I’ve done this for now:

Example of config.php

// Define ENVIRONMENT in this file to set different configs
include "config/config.local.php";

switch (ENVIRONMENT) {
	case "production";
		// Database
		$config['dbHost'] = "XXXX";
		$config['dbUser'] = "YYYY";
		$config['dbPass'] = "ZZZZ";
		$config['dbName'] = "AAAA";
		break;

	case "staging";
		// Database
		$config['dbHost'] = "localhost";
		$config['dbUser'] = "CCCC";
		$config['dbPass'] = "DDDD";
		$config['dbName'] = "AAAA";
		break;

	default: // local dev
		// Database
		$config['dbHost'] = "localhost";
		$config['dbUser'] = "FFFF";
		$config['dbPass'] = "GGGG";

		// To handle branched DBs
		switch (ENVIRONMENT) {
			default:
				$config['dbName'] = "AAAA";
				break;
		}
		break;
}

/* These should not need to be altered */

// Logging
$config['logFile'] = "logger";

// Other stuff
$config['otherStuff'] = "Stuff";

So on production and staging, the config.local.php is something like:

<?php
define("ENVIRONMENT", "production");
?>

But on my local server, I might have a number of different feature branches in development, and sometimes the DB structure is incompatible with other branches, so I need multiple DBs. For this, I use a config.local.php which strips the name of the branch from “svn info”:

<?php
define("ENVIRONMENT", shell_exec("svn info | grep '^URL:' | egrep -o '(tags|branches)/[^/]+|trunk' | egrep -o '[^/]+$'"));
?>

Then the inner switch() for local development becomes something like:

		// To handle branched DBs
		switch (ENVIRONMENT) {
			case "feature-branch-XYZ":
				$config['dbName'] = "AAAA-XYZ";
				break;
			default:
				$config['dbName'] = "AAAA";
				break;
		}
		break;

I also add a conditional just below <body> on the page code:

		<?php
// Show the current working tree on development sites
		if (ENVIRONMENT != 'production') {
			$switch = shell_exec("svn info | grep '^URL:' | egrep -o '(tags|branches)/[^/]+|trunk' | egrep -o '[^/]+$'");
			echo "Working on " . $switch;
		}
		?>

I’m hoping this will help keep track of things a little easier. It’ll do for now.

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>