26 January 2011 0:04:03
Over at Sleeping Giant Studios, we have a number of developers all working on the same WordPress (WP) projects and using SVN (via Beanstalk) for source control. As such, each developer’s workstation has a checked-out copy of the project codebase. (And WordPress itself is in a subdirectory of the project as an SVN:External, but that’s another post for another time.)
We’re also using a shared development database meaning that everyone develops against the same database (and data) while maintaining separate working copies of the project codebase. (We do this to reduce the amount of system administration we have to do on each workstation and also to ease content-entry sharing.) Working this way presents some problems because WP is designed to run against a single URL which gets stored in the database as a few different wp_options.
The workaround for this is actually pretty simple. We define all of the URL options that WordPress needs as PHP constants in wp-config.php skipping whatever is stored in the DB. Using the examples on the wp-config.php Codex page, we can even set these constants dynamically using PHP $_SERVER globals so we never have to hard code them to a specific URL. For a default installation of WP in the root folder of a site we define a set of PHP constants in wp-config.php like so:
/** Sanitize SERVER_NAME, just in case **/ $server_name = htmlentities( $_SERVER['SERVER_NAME'] ); /** Custom WordPress core location **/ define('WP_SITEURL', 'http://' . $server_name); /** Custom home location **/ define('WP_HOME', 'http://' . $server_name); /** Custom wp-content location settings **/ define('WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/wp-content'); define('WP_CONTENT_URL', 'http://' . $server_name . '/wp-content'); define('WP_PLUGIN_DIR', $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins'); define('WP_PLUGIN_URL', 'http://' . $server_name . '/wp-content/plugins'); define('PLUGINDIR', $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins');
This allows each developer’s working copy to run using their workstation’s URL regardless of the values set in the database.
As with everything in life, there are a few issues with running this way. Here’s a few we’ve noticed:
- A rare plugin might not work this way. Frankly, incompatible plugins are few & far between and we choose to avoid them because not using WP’s plugin best practices is foolish.
- Posts (or pages or anything in the wp_posts table) added by each developer end up with GUID’s set to their workstation’s URL in the wp_posts table. There are a couple other places this might creep up (in wp_options and some plugins’ custom tables for example). This hasn’t caused any problems for us. We tend to do a full search and replace for URL’s in the DB before going to staging or live deployments anyway. This just means running the search and replace script against several URLs instead of just one. We use Spectacu.la’s SearchReplaceDB.php script to accomplish this. It finds and replaces serialized and non-serialized strings throughout the entire DB.
In the future, I’ll planning to write up how we setup each project as an SVN repository using SVN:Externals to manage the WordPress core codebase and all the WordPress hosted plugins.