Local WordPress development with a better wp-config.php

Posted on by Chris

Responsible developers don’t work live. Working on a local copy of a site and only pushing it live when it’s ready is one of those sensible development practices that everyone should follow, but it can introduce some hitches when working with WordPress. Luckily, wp-config.php is the one core file that’s never overwritten by a WordPress update, so it’s safe to rewrite it to be a bit more useful. The wp-config.php file is generated from wp-config-sample.php by the WordPress install script and anyone who’s worked with WordPress will be familiar with the contents so I won’t list them in full, but you can view the default contents of wp-config-sample.php in the WordPress SVN repository.

Our local and remote environments will likely be very different. They’ll likely have different database details, for example. In order to make our wp-config.php portable, let’s start by setting a constant that’ll help us distinguish which environment we’re running in:

if ($_SERVER['REMOTE_ADDR']=='127.0.0.1') {
 
    /** We're accessing WordPress from localhost, which means this is our dev setup */
    define('WP_ENV', 'development');
} 
else {
    define('WP_ENV', 'production');
}

Then we need to specify a different set of database details for our development and production sites:

if(WP_ENV == 'development') {
 
	/** We're working locally, so use the dev database details */
 
	define('DB_NAME', 'database_name_here');
	define('DB_USER', 'username_here');
	define('DB_PASSWORD', 'password_here');
	define('DB_HOST', 'localhost');
	define('DB_CHARSET', 'utf8');
	define('DB_COLLATE', '');
 
}
elseif(WP_ENV == 'production' {
 
	/** Live database details */
 
	define('DB_NAME', 'database_name_here');
	define('DB_USER', 'username_here');
	define('DB_PASSWORD', 'password_here');
	define('DB_HOST', 'localhost');
	define('DB_CHARSET', 'utf8');
	define('DB_COLLATE', '');
 
}

The database isn’t the only way in which our dev and live environments will differ. Experienced WordPress developers will be familiar with the WP_DEBUG flag, which controls the display of errors. We never want to show errors on a live site, but it can be very useful for development. We can also log errors to file to help with troubleshooting on a live site, so let’s add a little conditional magic after the WP_DEBUG flag, based on our WP_ENV constant:

/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
 */
define('WP_DEBUG', false);
 
if(WP_DEBUG == true) {
	if(WP_ENV == 'production') {
 
		/** Don't display WP errors */
		define('WP_DEBUG_DISPLAY', false);
 
		/** Log errors to debug.log in /wp-content instead */
		define('WP_DEBUG_LOG', true);
 
		/** Suppress PHP errors, which are normally turned on by WP_DEBUG */
		@ini_set('display_errors',0);
 
	}
	elseif(WP_ENV == 'development') {
 
		/** Display errors on-screen */
		define('WP_DEBUG_DISPLAY', true);
 
		/** Log errors to debug.log in /wp-content as well, for reference */
		define('WP_DEBUG_LOG', true);
 
	}
}

Finally, one of the most annoying things about developing locally and pushing to a live server is the broken links that occur because WordPress stores URLs in the database. This next snippet has a double-headed benefit: it means you can simply replicate your live database in your dev environment without having to worry about changing URLs in the database, and on the live site it saves a couple of database queries because WordPress doesn’t have to hit the database every time the site URL is needed:

if(WP_ENV == 'development') {
 
	/** Development domain goes here */
	define('WP_SITEURL', 'http://localhost/example');
	define('WP_HOME', 'http://localhost/example'); 
 
}
elseif(WP_ENV == 'production') {
 
	/** Live domain goes here */
	define('WP_SITEURL', 'http://example.com');
	define('WP_HOME', 'http://example.com'); 
 
}

Of course, I’ve included a lot of unnecessary conditionals along the way for the sake of example, so let’s pull all these snippets together into an efficient, portable wp-config.php:

<?php
/**
 * The base configurations of the WordPress.
 *
 * This file has the following configurations: MySQL settings, Table Prefix,
 * Secret Keys, WordPress Language, and ABSPATH. You can find more information
 * by visiting {@link http://codex.wordpress.org/Editing_wp-config.php Editing
 * wp-config.php} Codex page. You can get the MySQL settings from your web host.
 *
 * This file is used by the wp-config.php creation script during the
 * installation. You don't have to use the web site, you can just copy this file
 * to "wp-config.php" and fill in the values.
 *
 * @package WordPress
 */
 
if ($_SERVER['REMOTE_ADDR']=='127.0.0.1') {
 
    /** We're accessing WordPress from localhost, which means this is our dev setup */
    define('WP_ENV', 'development');
} else {
    define('WP_ENV', 'production');
}
 
/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
 */
define('WP_DEBUG', false);
 
if(WP_ENV == 'development') {
 
	/** Development domain goes here */
	define('WP_SITEURL', 'http://localhost/example');
	define('WP_HOME', 'http://localhost/example');
 
	/** We're working locally, so use the dev database details */
 
	define('DB_NAME', 'database_name_here');
	define('DB_USER', 'username_here');
	define('DB_PASSWORD', 'password_here');
	define('DB_HOST', 'localhost');
	define('DB_CHARSET', 'utf8');
	define('DB_COLLATE', '');
 
        if(WP_DEBUG == true) {
 
            /** Display errors on-screen */
            define('WP_DEBUG_DISPLAY', true);
 
            /** Log errors to debug.log in /wp-content as well, for reference */
            define('WP_DEBUG_LOG', true);
        }
}
elseif(WP_ENV == 'production') {
 
	/** Live domain goes here */
	define('WP_SITEURL', 'http://example.com');
	define('WP_HOME', 'http://example.com'); 
 
 
	/** Live database details */
 
	define('DB_NAME', 'database_name_here');
	define('DB_USER', 'username_here');
	define('DB_PASSWORD', 'password_here');
	define('DB_HOST', 'localhost');
	define('DB_CHARSET', 'utf8');
	define('DB_COLLATE', '');        
 
        if(WP_DEBUG == true) {
 
            /** Don't display WP errors */
            define('WP_DEBUG_DISPLAY', false);
 
            /** Log errors to debug.log in /wp-content instead */
            define('WP_DEBUG_LOG', true);
 
            /** Suppress PHP errors, which are normally turned on by WP_DEBUG */
            @ini_set('display_errors',0);         
        }
}
 
 
/**#@+
 * Authentication Unique Keys and Salts.
 *
 * Change these to different unique phrases!
 * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
 * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
 *
 * @since 2.6.0
 */
define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');
 
/**#@-*/
 
/**
 * WordPress Database Table prefix.
 *
 * You can have multiple installations in one database if you give each a unique
 * prefix. Only numbers, letters, and underscores please!
 */
$table_prefix  = 'wp_';
 
/**
 * WordPress Localized Language, defaults to English.
 *
 * Change this to localize WordPress. A corresponding MO file for the chosen
 * language must be installed to wp-content/languages. For example, install
 * de_DE.mo to wp-content/languages and set WPLANG to 'de_DE' to enable German
 * language support.
 */
define('WPLANG', '');
 
/* That's all, stop editing! Happy blogging. */
 
/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
	define('ABSPATH', dirname(__FILE__) . '/');
 
/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

This file is also available as a Gist on GitHub.

This entry was posted in WordPress. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *