Codex tools: Log in
Whether you're developing WordPress plugins, WordPress themes, or rolling out a new site based on a customized version of WordPress, it's often helpful to be able to mirror your live site on your local system for development. This is common for commercial sites, where you have a live production server but you also need a development and/or staging server, which is run locally to test plugins, mods, themes, and everything else that you don't want to do on the live production server. For example, your live site could be http://www.example.com/blog and your development site might be http://localhost/example.com/blog. However, WordPress serves pages with embedded absolute URLs based on the absolute site URL configured in your database, so none of the links on your development site will work.
Assuming that WordPress on your local machine is accessible via "http://localhost/local_folder_name", then update the WP_OPTIONS for option_name siteurl and home to be "http://localhost/local_folder_name".
SELECT * FROM wp_options WHERE option_name = "home" OR option_name = "siteurl"; UPDATE wp_options SET option_value = "http://localhost/local_folder_name" WHERE option_name = "home" OR option_name = "siteurl"
Each time you download a copy of your database from live down to your development server, you'll have to remember to update your database again. Fortunately, there's a simple hack for functions.php that can doesn't require you to update your database. Note: with this hack activated, Wordpress will IGNORE values you've configured for siteurl and home in your Options, and work them out for itself.
Contents |
You need to intercept two values that are called from the wp_options database, which are siteurl and home, and normally set in your options panel (WP base URL, and website homepage; if your whole site is WP they can be the same). There are a few potential ways to do this.
A method that works for sure is to manually edit get_option in functions.php. This will intercept every pull of these options. You want a condition to check if your user is already visiting the 'dev' version of the site, and in that case, to return the right values.
For example, if your normal installation is http://my.web.zz/wordpress and your development one is http://my.web.zz/wordpress-dev you can do the following; the example assumes you want siteurl=home for simplicity.
/* put this at the very start of get_option() in wp-includes/option.php */
if ($option == 'siteurl' || $option == 'home') {
$currenturi = $_SERVER['REQUEST_URI'];
$mypos = strpos($currenturi, 'wordpress-dev'); /* are we looking at dev site right now? */
if ($mypos !== false)
return 'http://my.web.zz/wordpress-dev';
} /* continue on with normal method, if we are not looking at dev site */
As well, be sure to update .htaccess in your development version.
The solution proposed below is cleaner but doesn't seem to actually work, because the filters don't seem to be applied early enough to pre_option_siteurl and pre_option_home for WP_HOME and friends to help.
You need to add code to your wp-config.php that assigns the right values of WP_HOME and WP_SITEURL to reflect the current location of WordPress, whether it's the live site or a local staging server.
To do this, simply add one of the following code sections to your wp-config.php above the last require_once statement.
Either this function:
function WP_LOCATION () {
$script_path = realpath(dirname($_SERVER['SCRIPT_FILENAME']));
$wp_base_path = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..');
$web_subfolder = substr( $script_path, strlen($wp_base_path));
$wp_path = $web_subfolder ? substr( dirname($_SERVER['SCRIPT_NAME']), 0, -strlen($web_subfolder) ) : dirname($_SERVER['SCRIPT_NAME']) ;
$retval = 'http' . ($_SERVER['HTTPS'] ? 's' : null) . '://' . $_SERVER['HTTP_HOST'] . $wp_path ;
return $retval;
}
$wpLocation = WP_LOCATION();
define('WP_HOME',$wpLocation);
define('WP_SITEURL',$wpLocation);
define('WP_CONTENT_URL',$wpLocation."/wp-content");
Or alternately, you can add the following code, replacing LIVEURL and STAGINGURL with the locations for your live and staging servers:
$currenthost = $_SERVER['HTTP_HOST'];
$mypos = strpos($currenthost, 'localhost');
if ($mypos === false) {
define('WP_HOME','LIVEURL');
define('WP_SITEURL','LIVEURL');
} else {
define('WP_HOME','STAGINGURL');
define('WP_SITEURL','STAGINGURL');
}
Edit the file wp-includes/options.php
In the function get_option, add this hack immediately after the line which says global $wpdb. It should look like the following:
function get_option( $setting ) {
global $wpdb;
/* Siteurl hack */
if( 'siteurl' == $setting or 'home' == $setting )
{
$_REAL_SCRIPT_DIR = realpath(dirname($_SERVER['SCRIPT_FILENAME']));
// filesystem path of this page's directory (index.php or whatever)
$_REAL_BASE_DIR = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..');
// filesystem path of this file's parent directory
// (that wp-includes is within)
$_MY_PATH_PART = substr( $_REAL_SCRIPT_DIR, strlen($_REAL_BASE_DIR));
// just the subfolder part between <installation_path> and the page
$INSTALLATION_PATH = $_MY_PATH_PART
? substr( dirname($_SERVER['SCRIPT_NAME']), 0, -strlen($_MY_PATH_PART) )
: dirname($_SERVER['SCRIPT_NAME'])
;
// we subtract the subfolder part from the end of <installation_path>,
// leaving us with just <installation_path> :)
$value = 'http' . ($_SERVER['HTTPS'] ? 's' : null) .
'://' . $_SERVER['HTTP_HOST'] . $INSTALLATION_PATH
;
return $value;
}
/* end Siteurl hack */
// Allow plugins to short-circuit options.
$pre = apply_filters( 'pre_option_' . $setting, false );
if ( false !== $pre )
return $pre;
// ... rest of the function continues (do not copy this line!)
The hack goes in wp-includes/functions.php
/* Options functions */
function get_settings($setting) {
global $wpdb;
$value = wp_cache_get($setting, 'options');
</tt>
<div style="background-color: #f9f9f9;"><tt>
/* Siteurl hack */
if( 'siteurl' == $setting or 'home' == $setting ) {
$_REAL_SCRIPT_DIR = realpath(dirname($_SERVER['SCRIPT_FILENAME']));
// filesystem path of this page's directory (index.php or whatever)
$_REAL_BASE_DIR = realpath(dirname(__FILE__) .
DIRECTORY_SEPARATOR . '..');
// filesystem path of this file's parent directory
// (that wp-includes is within)
$_MY_PATH_PART = substr( $_REAL_SCRIPT_DIR, strlen($_REAL_BASE_DIR));
// just the subfolder part between <installation_path> and the page
$INSTALLATION_PATH = $_MY_PATH_PART
? substr( dirname($_SERVER['SCRIPT_NAME']), 0, -strlen($_MY_PATH_PART) )
: dirname($_SERVER['SCRIPT_NAME'])
;
// we subtract the subfolder part from the end of <installation_path>,
// leaving us with just <installation_path> :)
$value = 'http' . ($_SERVER['HTTPS'] ? 's' : null) .
'://' . $_SERVER['HTTP_HOST'] . $INSTALLATION_PATH
;
}
/* end siteurl hack */
if ( false === $value ) {
if ( defined('WP_INSTALLING') )
$wpdb->hide_errors();
With this hack in place, you can now use exactly the same database and exactly the same files for both your local and remote WordPress install. Possibly the only thing you'd need to do is put different settings in wp-config.php if you want to use a remote database.
Note: this hack is untested if your server runs PHP in Safe Mode. If you have any problems, please post them on the Discussion page.