I was the IT Director for an online marketing company and the CEO one day told me that we were going to now start using WordPress as the CMS for all our sites. I don’t mind WordPress, in fact this and many of the other sites that I have made are in WordPress. This particularly annoyed me because I had spent the past month or so building a custom CMS and engineering the server around this CMS which was now essentially going to be wadded up and thrown in the trash. One of the biggest reasons I did not want to got the WordPress route is because I was building the server around a centralized code base as opposed to a distributed one like in WordPress. I figured that this was something I could get around and make a single WordPress install stretch to be used for all of our sites. This strategy pays for itself when it comes time to upgrade the WordPress core or any well used plugin and also for managing users when an employee with access to nearly all the customer’s sites leaves the company.
At the core, I installed one WordPress, created a versatile wp-config.php file and some shell scripts to create new sites, launch from development to production, and update development from live (needed for when the customers made their changes). This was a long process to setup and get the bugs worked out, but once it was setup, I liked it enough to do it on my own personal server. First, I am going to start with the wp-config.php file, but I am going to break it up into sections to explain each part
<?php
require_once "prepend.php";
First thing here is I included a prepend.php, which is an optional line of code for the grand scheme of things, but it can be very helpful. I used it to create all kinds of custom variables, objects, and methods that made my life as a developer so much easier because I knew that in all the sites on this server had them included because of that first line of code.
require_once "regconnect.php";
$result = mysql_query("
SELECT
dbschema
FROM
apache_vhosts
WHERE
host='".DOMAIN."'
LIMIT 1;");
if ($schema = mysql_fetch_array($result)) $schema = $schema[0];
else {
include "error.php";
exit();
}
mysql_close();
If you read my previous articles about dynamic virtual hosting, this part will make a lot more sense. In this server environment, I had a MySQL database table which acted essentially as the site registry. I, in fact, called it the Site Registry which is why I had a file regconnect.php that I included whenever I wanted to connect to the registry. So in this portion of the code, I connect to the site registry and figure out the database for this site based on the domain name used. The DOMAIN constant is actually defined in my prepend.php, but it is essentially interchangeable with $_SERVER[‘HTTP_HOST’]. I just used it to force all lower case and strip “www.” off the front of the host name. Once it finds the correct database, it sets it to the $schema variable, or if it fails to find the right database, it pulls in the error page and terminates the application. Side Note: all these includes and requires leveraged on me customizing the PHP path configuration so it knew where to find my global scripts
define('DB_NAME', $schema);
define('DB_USER', 'wordpress_user');
define('DB_PASSWORD', 'password');
define('DB_HOST', 'localhost');
$table_prefix = explode("_", $schema);
$table_prefix = $table_prefix[1]."_";
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
define('WPLANG', '');
define('ABSPATH', dirname(__FILE__));
define('WP_CONTENT_DIR', DOCROOT.'wp-content');
require_once ABSPATH.'wp-settings.php';
This part is the familiar as it is the part that you already have to do for any wp-config.php file sans all their comments. The biggest notation to make here was that I decided to go with a universal wordpress DB user and this was something that a came about out of protest. Originally, I stored a username and password for each site in the site registry, but when it came to writing the shell scripts for updating between development and production, I ended up going this route for simplicity sake. I know that there were numerous ways to get it working with each site having its own DB user, but with GRANT queries, it became a very convoluted process when trying to manage separate users and ultimately if a user wanted to pull their site from our hosting and host it elsewhere, I already had to write a different wp-config.php, so the ultimately the arguments for individual users started dwindling in lieu of simplicity.
if (PAGE == "wp-login.php") {
require "regconnect.php";
$result = mysql_query("
SELECT
*
FROM
wp_global_users;");
$insertusers = "
INSERT INTO
".$table_prefix."users VALUES (";
while ($user = mysql_fetch_assoc($result)) {
foreach ($user as $value) $insertusers .= "
'".$value."', ";
$insertusers = substr($insertusers, 0, -2)."), (";
}
$insertusers = substr($insertusers, 0, -3).";";
$result = mysql_query("
SELECT
*
FROM
wp_global_usermeta;");
$insertusermeta = "
INSERT INTO
".$table_prefix."usermeta
VALUES (";
while ($usermeta = mysql_fetch_assoc($result)) {
foreach ($usermeta as $value) $insertusermeta .= "
'".preg_replace("/^wp_/", $table_prefix, $value)."', ";
$insertusermeta = substr($insertusermeta, 0, -2)."), (";
}
$insertusermeta = substr($insertusermeta, 0, -3).";";
mysql_close();
mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
mysql_select_db(DB_NAME);
mysql_query("
DELETE FROM
".$table_prefix."users
WHERE
ID < 1001;");
mysql_query($insertusers);
mysql_query("
DELETE FROM
".$table_prefix."usermeta
WHERE
user_id < 1001;");
mysql_query($insertusermeta);
mysql_close();
}
?>
This was probably the part that I liked the most about this strategy of using a single WordPress install. I managed central user tables in the same schema as my site registry for all global WordPress users. This way I could give my writers and my designers the right permissions and manage them centrally so that I could easily remove a user if they left the company (which that company was notorious about rapid turnovers mostly due to belligerent management). Now, the only problem was that the WordPress users work off of an auto-incrementing ID so the best way that I could do this was to create a reserve block at the lower numbers for the global users demarcated by a dummy account that I simply named "reserved" and gave it no real permissions (Subscriber). I assigned it an ID of 1000. Once this dummy account gets duplicated to the individual sites’s WordPress user table, then all site local accounts will automatically start from ID 1001.
The CEO of the company didn’t want the customer to see our accounts, so I also edited a file in wp-admin to only display the accounts which ID’s where greater than 1000. I didn’t like that solution as it was a change that I would have to redo with every update to the WordPress core, but as it was a one line change, it was not worth it to me to build a more automated way of doing it. Ultimately, I have no problems showing all the accounts in there and just explaining to the customers that those are our accounts. After all, even if they try to delete or edit the accounts, they just go back to the global settings every time anyone logs in.
Well, now that we have the wp-config.php file down, the next step would be my script for creating a new site which I will save for another post.
Leave a Reply