Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
How to use WordPress across environments without needing to mess with URLs in the database.
<?php
// This is the meat of the plugin and should go in mu-plugins/0-env-url-override.php
// Only load these filters if we're not in the production environment
if ( defined( 'ENV_NOT_PRODUCTION' ) && ENV_NOT_PRODUCTION ) {
// This always needs to be filtered
add_filter( 'site_url', 'env_filter_site_url', 0 );
// We don't filter home_url in the admin so that we get production URLs for posts.
// This does break certain links like "Preview/View Post", however.
// If local post permalinks in content isn't an issue, then the is_admin check should be removed
if ( ! is_admin() )
add_filter( 'home_url', 'env_filter_home_url', 0 );
// Output buffering will sweep up any remaining URLs and point them to local versions.
// This is only run in the front-end to allow media uploads to work correctly.
// However, the side effect is that images appear broken in the admin.
// This can be probably resolved by using a central CDN for all environments.
if ( ! is_admin() )
ob_start( 'env_str_replace_links' );
// This is our hack-around to fix links in the admin that point to our production URL because we don't run home_url in the admin
// This is less than ideal and still doesn't catch everything
add_action( 'admin_footer', 'env_str_replace_links_js', 99 ); // load late so we know jQuery is available
// Filter these URLs since they use constants that are defined very early.
add_filter( 'plugins_url', 'env_filter_site_url', 0 ); // This is needed mainly for the admin, otherwise output buffering handles the URLs
//add_filter( 'content_url', 'env_filter_site_url', 0 ); // This one shouldn't be needed since we have output buffering
// Filtering the permalink probably isn't necessary.
//add_filter( 'post_link', 'env_filter_home_url', 0 );
}
function env_filter_home_url( $url ) {
if ( strpos( $url, WP_HOME ) === 0 )
return str_replace( WP_HOME, ENV_LOCAL_HOME, $url );
return $url;
}
function env_filter_site_url( $url ) {
if ( strpos( $url, WP_SITEURL ) === 0 )
return str_replace( WP_SITEURL, ENV_LOCAL_SITEURL, $url );
return $url;
}
// Filter all content and replace any production URLs with appropriate dev URLs
// http://groups.google.com/group/wp-hackers/browse_thread/thread/55e8bf607c456b17/ab20214865c36726
function env_str_replace_links( $content ) {
$content = str_replace( WP_HOME, ENV_LOCAL_HOME, $content );
return $content;
}
function env_str_replace_links_js() {
// I'm sure this can be done in a cleaner way, but for now, speed wins over grace :)
?>
<script>
var env_home = '<?php echo esc_js( WP_HOME ); ?>';
var env_home_replace = '<?php echo esc_js( ENV_LOCAL_HOME ); ?>'; // using the constants directly, because home_url() isn't filtered
var env_siteurl = '<?php echo esc_js( WP_SITEURL ); ?>';
var env_home_replace = '<?php echo esc_js( ENV_LOCAL_SITEURL ); ?>';
jQuery( 'a[href]' ).each( function() {
var href_replace = '',
href = this.getAttribute( 'href' );
if ( -1 < href.indexOf( env_home ) )
href_replace = href.replace( env_home, env_home_replace );
else if ( -1 < href.indexOf( env_siteurl ) )
href_replace = href.replace( env_siteurl, env_siteurl_replace );
if ( href_replace )
this.setAttribute( 'href', href_replace );
} );
</script>
<?php
}
// Debug
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( var_export( array(
'home_url: ' . home_url(),
'WP_HOME: ' . WP_HOME,
'site_url: ' . site_url(),
'WP_SITEURL: ' . WP_SITEURL,
'LOCAL_HOME: ' . ENV_LOCAL_HOME,
'LOCAL_SITEURL: ' . ENV_LOCAL_SITEURL,
'WP_CONTENT_DIR: ' . WP_CONTENT_DIR
), true ) );
} );
// Remote: mysite.com
// Stating: preprod.mysite.com
// QA: qa.mysitetesting.com
// Local: localhost/mysite
// Production URLs are hardcoded in wp-config.php using the WP_HOME and WP_SITEURL constants.
// When $_SERVER['HTTP_HOST'] doesn't match our production URL, we assume that we're in a non-production environment.
// In this context, we filter production URLs and replace with local URL.
// We use output buffering to sweep up any URLs missed by the filters.
<?php
// This code should be added to wp-config.php
// Hard-code the values of our production environment
define( 'WP_HOME', 'http://notlocal.digitalize.ca' );
define( 'WP_SITEURL','http://notlocal.digitalize.ca' );
switch ( $_SERVER['HTTP_HOST'] ) {
case 'localhost': // Our localhost install is in a subfolder, so we're overriding the URLs here
define( 'ENV_LOCAL_HOME', 'http://localhost/wp31' );
define( 'ENV_LOCAL_SITEURL', 'http://localhost/wp31' );
break;
// Other environments that use subfolders should go here as well
// Use this to customize other constants across environments
default: // default to HTTP_HOST
define( 'ENV_LOCAL_HOME', 'http://' . $_SERVER['HTTP_HOST'] ); // this needs be changed if https should be supported
define( 'ENV_LOCAL_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] ); // this needs be changed if https should be supported
break;
}
define( 'ENV_NOT_PRODUCTION', WP_HOME !== ENV_LOCAL_HOME );
if ( ENV_NOT_PRODUCTION ) {
// Override the COOKIEHASH in non-production environments
// We need to do this since COOKIEHASH is based off the siteurl and auth will fail
define( 'COOKIEHASH', md5( ENV_LOCAL_HOME ) );
}
@wpmnger

This comment has been minimized.

Copy link

commented Sep 12, 2013

Using a variant of your code here and added the following for WPML to work:
add_filter ( 'option_home' , 'env_filter_home_url'); // This is needed to enable WPML

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.