9

For doing local development on a WordPress site (http://www.example.com), I was previously overriding the WP_SITEURL and WP_HOME values in wp-config.php like so:

define('WP_SITEURL', 'http://local-example/');
define('WP_HOME', 'http://local-example/');

This would allow me to copy the database and site files to a local server, and make modifications as necessary, testing on the local install.

It was then necessary to convert the install to a WordPress Multisite so that users, authentication, plugins, etc. could be shared between the main site and a secondary site, hosted on a subdomain (http://second.example.com).

The method above to override the values in the wp_options table no longer works, but I am unsure the proper way to set a value for the entries in wp_blogs as well as the wp_2_options table for the primary and subdomain.

Updating my HOSTS file is somewhat of a workaround, but it not ideal (I am not able to compare to the live site, etc). Running a script to change the database values is another option I have tried, but is slightly more cumbersome, so my questions is whether or not there is an option in MultiSite to override these values in a settings file, such as wp-config.php, and if so what it would look like.

doublesharp
  • 26,888
  • 6
  • 52
  • 73

5 Answers5

14


Update: full updated plugin code with additional description can be found here: http://justinsilver.com/technology/wordpress/wordpress-plugins/wordpress-plugin-wp-server-migration/
I was able to come up with a solution with the help of @user916011. I needed to be able to copy the wp_options table(s) to my development environment as they contain configurations that are needed. To overcome the issue of not being able to set the WP_SITEURL and WP_HOME values in MultiSite, I wrote a custom filter to replace the _config_wp_siteurl() and _config_wp_home() functions that are available for non-multisite installs that is included in a plugin that is available network-wide and is configured in wp-config.php. I am then able to copy all of the database tables except wp_site and wp_blogs to a local database.

I highly recommend the URL Token Replacement Techniques for WordPress 3.0 article by Chris Murphy to help handle URLs in your content.

This example assumes a subdomain multisite install, with a domain of example.com and two subdomains, www.example.com and second.example.com. The local development URLs will be www.example.local and second.example.local respectively.

Database Changes:

Update the domain value in wp_site:

UPDATE wp_site SET domain = 'example.local' WHERE domain = 'example.com';

Update the domain value(s) in wp_blogs:

UPDATE wp_blogs SET domain = 'www.example.local' WHERE domain = 'www.example.com';
UPDATE wp_blogs SET domain = 'second.example.local' WHERE domain = 'second.example.com';

Plugin Code: The following plugin should be installed network-wide.

<?php
/*
Plugin Name: MultiSite WP_HOME and WP_SITEURL
Plugin URI: http://doublesharp.com/
Description: Allows wp_options values to be overwritten in wp-config.php for MultiSite
Author: Justin Silver
Version: 1.0
Author URI: http://doublesharp.com
License: GPL2
*/

function _ms_config_wp_siteurl( $url = '' ) {
    if (is_multisite()):
        global $blog_id, $current_site;
        $cur_blog_id = defined('BLOG_ID_CURRENT_SITE')? BLOG_ID_CURRENT_SITE : 1;
        $key = ($blog_id!=$cur_blog_id)? $blog_id.'_' : '';
        $constant = 'WP_'.$key.'SITEURL';
        if ( defined( $constant ) )
            return untrailingslashit( constant($constant) );
    endif;
    return $url;
}
add_filter( 'option_siteurl', '_ms_config_wp_siteurl' );

function _ms_config_wp_home( $url = '' ) {
    if (is_multisite()):
        global $blog_id;
        $cur_blog_id = defined('BLOG_ID_CURRENT_SITE')? BLOG_ID_CURRENT_SITE : 1;
        $key = ($blog_id!=$cur_blog_id)? $blog_id.'_' : '';
        $constant = 'WP_'.$key.'HOME';
        if ( defined( $constant ) )
            return untrailingslashit( constant($constant) );
    endif;
    return $url;
}
add_filter( 'option_home',    '_ms_config_wp_home'    );
?>

Configure wp-config.php:

Add new constants to wp-config.php. The primary site should use the standard WP_HOME and WP_SITEURL and the tertiary URLs should use WP_{$blog_id}_HOME and WP_{$blog_id}_SITEURL

define('WP_HOME',      'http://www.example.local');
define('WP_SITEURL',   'http://www.example.local');
define('WP_2_HOME',    'http://secondary.example.local');
define('WP_2_SITEURL', 'http://secondary.example.local');
TZHX
  • 5,291
  • 15
  • 47
  • 56
doublesharp
  • 26,888
  • 6
  • 52
  • 73
  • No problem, I ended up expanding it a bit to do more stuff including replacing links in the content here: http://justin.ag/technology/wordpress-plugins/wordpress-plugin-wp-server-migration/ The meta hooks are commented out because I ran into some issues (which might have been related to caching) but i have been using it on one of my multisites for a while with no problems. You need to define a `WP_DEVELOPMENT=true` constant to do the URL rewriting, the url token replacement should run all the time. – doublesharp May 01 '13 at 04:27
  • The last defines saved me after trying plugins and everything... BUT I also had to revisit the network wordpress admin page and resave each site page. – shaneonabike Apr 01 '15 at 17:51
  • WP_HOME and WP_SITEURL should not have any effect in MS – ar099968 Jun 01 '16 at 13:25
  • @ar099968 that is correct, and the exact problem that I was having. I was leveraging them before moving to MultiSite and needed a way to achieve the same functionality, which the plugin I wrote largely does. – doublesharp Dec 01 '16 at 18:33
1

You could use the update_option in functions.php

update_option("siteurl","http://example.com");
update_option("home","http://example.com");
Samuel Cook
  • 16,620
  • 7
  • 50
  • 62
  • The problem with this solution is that when I run the site locally, its URL is `http://local-example/` which doesn't match up to the database value of `http://www.example.com` in the case of the primary site. Because of this, none of the code in `functions.php` is executed, so the options aren't updated. Chickens and eggs. – doublesharp Oct 18 '12 at 17:10
1

There's a similar question being asked here: Team Development of a Wordpress Site which I provided a possible solution for. In your case, you may not want to go to that extent (though it would be very flexible); however, you could always look at the portion of the answer that mentions a domain-replacement technique.

I've outlined that solution here: URL Token Replacement Techniques...

Community
  • 1
  • 1
user916011
  • 505
  • 5
  • 8
  • Nice, that actually has a lot of great info, especially the URL Token Replacement. Unfortunately, it doesn't totally help in my case because I need to override actual database values (from what I can tell looking at `wp-includes/ms-settings.php`. – doublesharp Oct 18 '12 at 17:12
  • Basically, you're in Case 2 of the solution I've outlined in that other post. It's a consistent problem with WP (though not native to WP alone), and unfortunately, there's no easy solution for the problem -- unless you want to do some proxy magic or create some really complex routing rules in an `.htaccess` file. My experience with WP MU/Multi-site is that you need to configure your environments beforehand (with the approach I've outline) before you get started. Otherwise, it's a lot of SQL queries to replace values in your DB. – user916011 Oct 18 '12 at 17:19
  • Technically in Case 2, but the site isn't live so I can do whatever I need as far as setup. The problem isn't URLs in the content per se, it's the saved URLs in the `wp_options['siteurl']` (primary site), `wp_site['domain']` (MultiSite site), `wp_blogs['domain']` (primary, second blogs) and `wp_2_options['siteurl']` (secondary site). Previously I only had to worry about `wp_options['siteurl']` and could override that in `wp-config.php`, but I don't see how to do this without updating these table values every time I copy down the database. Ignoring the content URLs for now. – doublesharp Oct 18 '12 at 17:29
  • I actually may have just thought of a solution using your approach and some code I have written to override the values in `wp_options` and `wp_2_options` - If I setup custom a dev version of `wp_site` and `wp_blogs` with the values changed from production and not copy these down for dev work. I should then be able to use the custom wp-config.php values (my implementation is slightly different from yours, but the same principle). The problem I was having is that the `ms-settings.php` file has some hard coded queries to look up the blog_id, etc. – doublesharp Oct 18 '12 at 17:34
  • 1
    See the last part of that post on synchronization. The thing is: if you have a development environment that's separated from the staging environment, you don't need to dump every table, e.g. wp_options. You only need to dump the relevant content tables, that way you won't *have* to change the values in your development sandbox. So, what should happen here is that content promotion go upstream from staging to production, where as mirroring happens downstream from staging to your sandbox. This way each environment only needs to be configured once, leaving only content to be promoted. – user916011 Oct 18 '12 at 17:34
  • Exactly my thoughts (just posted) though I *do* need wp_options. I have some code that should fix that for me however, will post an update if it actually works :) – doublesharp Oct 18 '12 at 17:35
  • You could always write a bash script to run the SQL queries to update the wp_options tables if you're mirroring the DB to your development environment. Glad my post helped a little! – user916011 Oct 18 '12 at 17:42
  • Thanks a lot for your suggestions, I just posted the answer I came up with, and will upvote your supporting posts accordingly. – doublesharp Oct 18 '12 at 18:09
  • You came up with a very nice solution for the wp_options issue -- I've rarely had to deal with it, but now I at least have a good strategy to reference when I need to address it. Congrats! – user916011 Oct 18 '12 at 18:17
1

I had the same issue and wanted a solution as similar to defining WP_HOME & WP_SITEURL in wp-config.php as possible.

I can't use a plugin, because I am syncing with GIT and don't want to have that plugin in my repo and I would have to add the plugin everytime... I suppose it could be activated network wide through the wp_sitemeta table... but it wasn't ideal for me.

I came up with this solution.

Be sure to not sync wp_blogs, wp_site, wp_sitemeta. And then add this code to your local wp-config.php somewhere below $table_prefix:

/* Update local database */
mysql_connect( DB_HOST, DB_USER, DB_PASSWORD ) or die( mysql_error() );
mysql_select_db( DB_NAME );

$result = mysql_query("SELECT * FROM `". $table_prefix ."blogs`") or die( mysql_error() );
while( $row = mysql_fetch_array( $result ) )
{
    $id = (1 == $row['blog_id']) ? '' : $row['blog_id'] .'_';
    mysql_query( "UPDATE `". $table_prefix . $id ."options` SET `option_value`='http://". $row['domain'] ."/' WHERE (`option_name`='siteurl' OR `option_name`='home')" ) or die( mysql_error() );
}

This will make sure your sites are synced up to your local wp_blogs table.

The only drawback is that when you add a new site, you do manually need to copy it into your wp_blogs table and update its local url.

doublesharp
  • 26,888
  • 6
  • 52
  • 73
Jake
  • 2,058
  • 2
  • 24
  • 33
  • 1
    I can't believe I didn't think about doing it that way. This will run the update on every page load - you could use a value in the options table to determine if you need to run the update your not to prevent this even though it's not that much of a performance hit. PDO or mysqli would be good for future proofing too, even though WordPress is still using the mysql_* extensions. – doublesharp May 02 '13 at 00:19
  • 1
    A further option if you wanted to be able to refresh the entire database would be to store the blog_id => url mappings in an array in `wp_config.php` and update the `blogs`, `sites`, and `options` tables using it. – doublesharp May 02 '13 at 00:23
  • There are definitely options. This is really simple. The array could be a good option too. I started to do it that way, but decided against it. I am not sure why now... maybe because the blogs table has the site ids in already... It is running on every page load, but since I am only using it locally I didn't care. I would refine it for a live environment, and I tend to comment it out when I am not using it. And it isn't nearly robust as the plugin. Obviously links in the content are still left unchanged for one, but I just wanted something simple and portable. – Jake May 03 '13 at 04:19
0

This question is too old to answer, but recently I faced a similar situation where I have to migrate my wp site from staging to production and it was painful as it is having 5 subsite.

After scratching my head for all day, I found a simple and useful solution.

Of course one have to make changes in wp-config.php.

Other then that you have to follow below steps.

Generate database dump using following command.

mysqldump -u [user name] –p [password] [options] [database_name] [tablename] > [FileName]

After that open that file in any editor.

Find and replace your old domain with new domain.

Now restore the database with dump you created.

mysql -u [user name] -p [password] [database name] < [file anme]
naim shaikh
  • 1,103
  • 2
  • 9
  • 20
  • 2
    This unfortunately won't work very reliably - if any of the options for meta fields contain a serialized value with the URL then just updating will break the arrays, etc if the length of the domain is different. – doublesharp Jun 07 '21 at 16:33
  • @doublesharp, it might, but in my case it worked perfectly, and still if there are multiple sites, one can toss the coin to this solution, it hardly took 5 minutes. Before make sure you have sqldump backup. – naim shaikh Jun 08 '21 at 04:17