Wp-config.php & Multiple environments

Sometimes a website runs on different servers and each instance has its own database and configuration. For example, I have a local copy for testing (“extreme” data to test performance, fake user accounts, debuging mode …), a staging copy (limited access and some fictional “beautiful” data for presentations) and a production copy (normal access, real data, no error reporting).

Managing multiple wp-config.php files is rather messy. There is a chance to overwite one by another on deploy or backup restoration etc. So I use a universal file with custom structure that switches configuration according to a current $_SERVER[SERVER_NAME].

I wonder if this method has issues/pitfalls? Are there any smarter alternatives?

Do you have projects with multiple environments?
What does your wp-config.php looks like?

P.S. I also define a constant ACCESS_TYPE (should rename it probably) that tells my theme what kind of environment is used. It helps to override some normal theme behavior. For example, I don’t need maintenance mode on my local copy obviously. So I can switch off all related plugins by a conditional hook without changing any settings manually etc.

Here is an rough example of “switching”:

<?php
// ...

/**
 * This file provides custom configurations for different environments/mirrors.
 * It switches settings according to a current $_SERVER[SERVER_NAME].
 *
 * Default environment settings
 *
 * 'db_charset'     - Database Charset to use in creating database tables.
 * 'db_collate'     - The Database Collate type. Don't change this if in doubt.
 * 'db_host'        - Database host name. Use 'localhost' if in doubt.
 * 'db_name'        - The name of the database for ClassicPress.
 * 'db_user'        - Database user name.
 * 'db_password'    - Database user password.
 * 'db_prefix'      - ClassicPress Database Table prefix.
 * 'access_type'    - Environment type (see below).
 * 'wp_debug'       - ClassicPress debugging mode.
 */

$default_environment = array(
	'db_charset'  => 'utf8',
	'db_collate'  => '',
	'db_host'     => 'localhost',
	'db_name'     => '',
	'db_password' => '',
	'db_prefix'   => 'wp_',
	'db_user'     => '',
	'access_type' => 'private',
	'wp_debug'    => false,
);


/** Custom environments settings */

$environments = array(
	'example.test'       => array(
		'db_name'         => 'local_database',
		'db_password'     => '',
		'db_user'         => 'root',
		'access_type'     => 'local',
		'wp_debug'        => true,
	),
	'example.stage'       => array(
		'db_name'         => 'staging_database',
		'db_password'     => '',
		'db_user'         => 'staging_database_user',
		'access_type'     => 'private',
		'wp_debug'        => true,
	),
	'example.com'   => array(
		'db_name'     => 'production_database',
		'db_password' => 'Sup3r^S3#rEtPa55w',
		'db_user'     => 'production_database_user',
		'access_type' => 'public',
		'wp_debug'    => false,
	),
);


/** Switching environment */

$env = $_SERVER['SERVER_NAME'];
$config = $default_environment;

if ( ! empty( $env ) && array_key_exists( $env, $environments ) ) {
	$config =  array_merge( $default_environment, $environments[ $env ] );
}

define('DB_NAME', $config['db_name'] );
define('DB_USER', $config['db_user'] );
define('DB_PASSWORD', $config['db_password'] );
define('DB_HOST', $config['db_host'] );
define('DB_CHARSET', $config['db_charset'] );
define('DB_COLLATE', $config['db_collate'] );

define('WP_DEBUG', $config['wp_debug']);

$table_prefix  = $config['db_prefix'];

/**
 * For developers: Environment type.
 *
 * May be used by themes or plugins to switch some behavior without changing
 * settings in DB (ignore maintenance mode for example).
 * - "private" -- authorization is required to view the site,
 *                maintenance mode is always on.
 * - "local"   -- site is visible to anyone,
 *                maintenance mode is ignored.
 * - "public"  -- site is visible to anyone, but maintenance mode
 *                can be activated  manually in admin settings.
 */
define('ACCESS_TYPE', $config['access_type']);

// ...
1 Like

I think you need a .env file. On each server you would have a .env file with your database configurations for that server and even the ACCESS_TYPE - I use APP_ENV but that is because I mostly work with Laravel now.

Here is a good article for setting it up: Secure Your WordPress Config with DotEnv

Just don’t forget to make sure the .env is in your .gitignore.

2 Likes

Intriguing method you’ve got there. The suggested article seems to tick all the right boxes :slight_smile:

Although, the original readme file of the PHP dotenv implementation makes me cringe harshly, because you still would have to edit your local server configuration (eg. .htaccess), depending on the available environment. The naivity of thinking all people instantly grok the fact that the .env file still has to either stay outside of the regular web directory, or has to be made inaccessible from the outside, is rather …baffling… astonishing…

cu, w0lf.

4 Likes

Thanks, @wadestriebel! This is probably a solution for this topic. I didn’t read the article yet, just looked through, but it seems to be a proper method and really “a smarter alternative”. I’ll learn details and play a bit with .env at the weekend.

P.S. This forum is quite useful. Funny, I haven’t asked technical questions on any forums for years, as the answers usually were too vague and common comparing to simple google search. And now I really feel the strength of community support. Getting exhaustive solution in an hour — that’s amazing. Cheers! )

5 Likes

This is what we aim for! Let us know how it goes and feel free to tag me this weekend if you run into any issues setting it up :slightly_smiling_face:

5 Likes

I hope I don’t go off topic but I have a scratch theme I use with OOP that implements this .env setup out of the box with it’s CLI

Maybe you could incorporate it’s use of composer to make the setup easier.

3 Likes