Issue
I am about to embark on some WordPress development in a multi person team environment. (3 or more people working on the same codebase at a time, each developing locally)
With other CMSes we have worked with, everyone has pointed their installs at the same database and because of how that CMS/database has worked, it has meant we can all have the same content feeding into our installs (located at differing urls) from the same database without much issue (other than occasionally having to sync uploads folders)
My question is, with WordPress, what prevents us from using this same approach and how can we solve these issues?
eg. Three copies of WordPress all running off of the same database.
http://dev.local/developer-a/
http://dev.local/developer-b/
http://dev.local/developer-c/
etc
I hope it goes without saying that this will only be in a development environment prior to launch.
Main issues
- References to specific urls within the database (
wp_posts
andwp_options
tables it seems) - If one person installs a plugin, the other installs won’t have it and will cause concurrency issues in the database
- Keeping uploads folders in sync
Current Solution
Currently I have the beginnings of a solution for the first issue in place. I place the following in a file in my mu-plugins folder.
The code essentially filters the post content as it goes into and out of the database by replacing any instance of the url with a unique token.
<?php
define('PORTABILITY_TOKEN', '{_portable_}');
function portability_remove_home($content)
{
$content = str_replace(get_option('home'), PORTABILITY_TOKEN, $content);
return $content;
}
add_filter('content_save_pre', 'portability_remove_home');
function portability_add_home($content)
{
$content = str_replace(PORTABILITY_TOKEN, get_option('home'), $content);
return $content;
}
add_filter('the_content', 'portability_add_home');
add_filter('the_editor_content', 'portability_add_home');
I have set the home and siteurl options via php using the environment of where WordPress is installed to work them out. (again, this is for development only) This means that to each individual install WordPresses post content will look like it is running on that url by the time it gets to the client.
<?php
if (!defined('WP_HOME'))
{
// define WP_HOME (aka url of install) based on environment.
// IF THIS ISN'T WORKING, DEFINE IT EARLIER.
define('WP_HOME', 'http://' . $_SERVER['HTTP_HOST'] . str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname(__FILE__) ) );
}
if (!defined('WP_SITEURL'))
{
// Assumes WordPress is in a separate directory called 'wp', relative to WP_HOME.
// IF IT'S DIFFERENT, DEFINE IT EARLIER.
define('WP_SITEURL', WP_HOME . '/wp');
}
The second and third issues seem solvable with the appropriate symlinks (all developing on the same machine)
Actual Questions
-
Can I improve my handling of the differing urls in anyway? Is there anything I have missed that will have the url hardcoded into the database?
-
Any gotchas I should be aware of with the symlinking?
-
Any other issues anyone can think of?
I realise these questions are very specific, if anything is unclear, comment on this and I will amend / clarify.
Thanks.
I will answer question 2, be aware that some values in the database are stored in serialised arrays. For example, if the length of your URL string changes and it’s in a serialised array, then you need to update the index for it.
You can use this PHP script to update all the values in serialised arrays, or run it from the command line in your own script
Question 1: You’ve got URLs going into and coming out of the database in more places than just the post content. I found URLs in
*_postmeta
,*_comments
, and*_options
(in addition to the ones you defined). This is not counting plugin activity and Custom Meta Field activity.Question 2: I will also sometimes symlink plugins for convenience, and most of the time it works. Sometimes it doesn’t. I can’t tell you the exact conditions that cause an issue but Javascript does seem to be a factor.
Question 3: I would expect trouble with the
*_options
table if anything. Things like activated plugins and the active theme are kept there, among a lot of other information is pretty site specific.