Wordpress - Can we use one WordPress installation for multiple databases, domains and content directories

As @tom-j-nowell said in comment to OP, multisite can make this easier.

Performance and security are not really a problem for multisite (at least, not more than they are for regular installations), but I do agree that multisite can sometimes be a problem, because a lot of plugins (either custom or 3rd party) may not work properly on multisite, or maybe because you want to keep users of different websites completely separated.

That said what you want to achieve is not that hard.

What you need to change between installation is:

  • plugins folder
  • themes folder
  • database settings

Those configuration can be done using constants in wp-config.php your only problem is how to switch them based on URL.

The server variable 'SERVER_NAME' should work for you, at least if your webserver is configured properly.

For example you can create a folder named /conf at the same level of wp-config.php file and /WordPress folder.

In that folder you can add some files:

  • branch1.domain.com.conf
  • branch2.domain.com.conf
  • branch3.domain.com.conf

inside each of them you can do something like

$branch = 'branch1';
$base_dir = dirname( __DIR__) . "/{$branch}";

defined( 'WP_CONTENT_DIR' ) or define( 'WP_CONTENT_DIR', $base_dir );

// be sure WP understand URLs correctly
defined( 'DB_HOME' ) or define( 'DB_HOME', "{$branch}.example.com" );
defined('WP_SITEURL') or define('WP_SITEURL', "{$branch}.example.com/WordPress");

// adjust DB settings  as needed
defined( 'DB_NAME' ) or define( 'DB_NAME', $branch );
defined( 'DB_USER' ) or define( 'DB_USER', $branch );
defined( 'DB_PASSWORD' ) or define( 'DB_PASSWORD', '********' );

unset( $base_dir, $branch );

This will change on each configuration file according to the "branch".

After that, in your unique wp-config.php you can so something like:

$defaults_conf = [
  'WP_CONTENT_DIR' => __DIR__ . '/branch1',
  'DB_HOST'        => 'localhost',
  'DB_NAME'        => 'branch1',
  'DB_USER'        => 'branch1',
  'DB_PASSWORD'    => '********',
];

$host = getenv('WORDPRESS_HOST') ?: $_SERVER['SERVER_NAME'];

if ($host && file_exists(__DIR__."/conf/{$host}.conf")) {
  require __DIR__."/conf/{$host}.conf";
}

array_walk($defaults_conf, function($value, $name) {
   defined($name) or define($name, $value);
});

unset($defaults_conf, $host);

What happen above is that based on the server name you load a different configuration file (if found) and if the configuration file does not define any of the default configuration (or if the file is not found) configuration are set per default.

Nice thing is that to add a new branch, you just need to create the branch folder and provide a .conf named after the new branch domain, and you are done, there's nothing to change on WP side.

The line:

 $host = getenv('WORDPRESS_HOST') ?: $_SERVER['SERVER_NAME'];

is where I get the domain name. As first option I'm using an environment variable, because there're chances $_SERVER['SERVER_NAME'] will not work on a command line context, such us when using WP CLI. In those situations you can set an environment variable to force WP to use settings from a specific branch.

Note that in branch-specific config files I'm changing the WP_CONTENT_DIR and that will automatically set plugins and themes folder to the related /plugins and /themes branch subfolders.

A possible issue here is if you want to share the /uploads folder (where files get uploaded).

By default that folder is a subfolder of content dir, so using workflow above it will be an /uploads subfolder of each branch root folder.

If that is not a problem for you, than just go with it, otherwise the easiest solution would be to make /uploads in each branch folder a symlink to the real uploads folder you want to share.