Context Sensitive WordPress Configs

by Tom Bedford

Looking back to when I first started to use content management systems I would manually update the config file each time I moved from a local to staging or live hosting environment. This meant changing the database and username and password to match those on the server the site would be on.

Working with Perch CMS I soon came across an answer on their support forum talking about a config file that would work across multiple locations without needing to go in and edit it before each upload. This has since been written up as a solution on the Perch website.

I’ve recently been using WordPress much more frequently for agency work and adapted the code to work with the wp-config.php file. The examples below assume you are making edits to this file so I’ve omitted wrapping the code in PHP tags.

What are we replacing?

You’ll have a section in your wp-config.php file that looks like the code below. In WordPress 4.1 this starts on line 17. By the end of the article we will have replaced all of the following:


// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'database_name_here');

/** MySQL database username */
define('DB_USER', 'username_here');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

Starting out

The starting point is retrieving the HTTP host of the site and storing it in a variable:


$http_host = getenv('HTTP_HOST');

Switch it up

You can then use a switch to run different code based on what is stored in the variable.

The following code defines a different database name based on the HTTP host. The options given here are a defined case for example.localhost representing my local server and a default value. The default value is used when there isn’t a match with any specified case, in this example that would be when the URL is not http://example.localhost. I typically enter the live server details as the default value.


$http_host = getenv('HTTP_HOST');

switch($http_host)

{

    // local server
    case('example.localhost') :
            /** The name of the database for WordPress */
            define('DB_NAME', 'local_database');
            break;

   // live domain
    default :
            /** The name of the database for WordPress */
            define('DB_NAME', 'live_database');
            break;
}

Case by case

You can define more than one case, here is the same example but adding in a staging domain for the site. I use a staging site to test code online and share it with clients without making it available to the public.


$http_host = getenv('HTTP_HOST');

switch($http_host)

{

    // local server
    case('example.localhost') :
            /** The name of the database for WordPress */
            define('DB_NAME', 'local_database');
            break;

    // staging server
    case('staging.example.com') :
            /** The name of the database for WordPress */
            define('DB_NAME', 'staging_database');
            break;

   // live domain
    default :
            /** The name of the database for WordPress */
            define('DB_NAME', ‘live_database');
            break;
}

Make it useful

You can add in as many options as you like in each case. Below I’ve filled in each case with the database name, database user name and database password. I’ve kept the comments that are in the wp-config.php file to help you locate which code to replace. At the bottom there are the hostname, charset and collate type which are common to all three environments so they can be declared outside of the switch.


// ** MySQL settings - You can get this info from your web host ** //

$http_host = getenv('HTTP_HOST');

switch($http_host)

{

    // local server
    case('example.localhost') :
            /** The name of the database for WordPress */
            define('DB_NAME', 'local_database');
            /** MySQL database username */
            define('DB_USER', 'local_user');
            /** MySQL database password */
            define('DB_PASSWORD', 'local_password');
            break;

    // staging domain
    case('staging.example.com') :
            /** The name of the database for WordPress */
            define('DB_NAME', 'staging_database');
            /** MySQL database username */
            define('DB_USER', 'staging_user');
            /** MySQL database password */
            define('DB_PASSWORD', 'staging_password');
            break;

   // live domain
    default :
            /** The name of the database for WordPress */
            define('DB_NAME', 'live_database');
            /** MySQL database username */
            define('DB_USER', 'live_user');
            /** MySQL database password */
            define('DB_PASSWORD', 'live_password');
            break;
}

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

Finishing touches

Finally (and one of the most useful additions I found) was hard coding the WP_HOME and WP_SITEURL values for each server. This means that you don’t need to manually edit the database when changing environments in order to keep your WordPress install and site links working. It has the added benefit of preventing these values from being edited inside the WordPress admin which could stop a client accidentally breaking their WordPress install.

Here’s the final code:


// ** MySQL settings - You can get this info from your web host ** //

$http_host = getenv('HTTP_HOST');

switch($http_host)

{

    // local server
    case('example.localhost') :
            /** The name of the database for WordPress */
            define('DB_NAME', 'local_database');
            /** MySQL database username */
            define('DB_USER', 'local_user');
            /** MySQL database password */
            define('DB_PASSWORD', 'local_password');
            /** WordPress Home URL */
            define('WP_HOME','http://example.localhost');
            /** WordPress Site URL */
            define('WP_SITEURL','http://example.localhost');
            break;

    // staging domain
    case('staging.example.com') :
            /** The name of the database for WordPress */
            define('DB_NAME', 'staging_database');
            /** MySQL database username */
            define('DB_USER', 'staging_user');
            /** MySQL database password */
            define('DB_PASSWORD', 'staging_password');
            /** WordPress Home URL */
            define('WP_HOME','http://staging.example.com');
            /** WordPress Site URL */
            define('WP_SITEURL','http://staging.example.com');
            break;

   // live domain
    default :
            /** The name of the database for WordPress */
            define('DB_NAME', 'live_database');
            /** MySQL database username */
            define('DB_USER', 'live_user');
            /** MySQL database password */
            define('DB_PASSWORD', 'live_password');
            /** WordPress Home URL */
            define('WP_HOME','http://example.com');
            /** WordPress Site URL */
            define('WP_SITEURL','http://example.com');
            break;
}

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

Be creative

This method does not have to be confined to a config file. You could switch out analytics code so it only tracks the live site, turn caching on and off, set whether a page is indexed or not based whether it’s on a local, staging or live server.

I’ve used it with Disqus before as comment area IDs are formed based on the URL which will be different for a local, staging or live site. In this way I don’t populate the Disqus account for the live site with IDs for local or staging URLs.