Why is changing the hostname for a WordPress site so hard?

Recently, some changes at work have me doing more WordPress work than I’ve ever done before. I am mainly helping a group within our division deploy the sites they are building for clients. After doing a few of these, I’m just stunned by how difficult it is to move a site from one domain to another.

Given how common it must be for WordPress developers to develop a site on one hostname, e.g. “dev.MYCLIENT.com” or “MYCLIENT.ourdevenvironment.com”, before moving it to its final destination, it’s really hard to believe how hard WordPress makes this.

Even worse is the fact that the thriving WordPress developer community hasn’t built a robust, bulletproof solution for this. Sure there are plugins like BackupBuddy that admittedly make it easier, but I don’t think there’s a tool out there that handles all the possibilities.

The problem, in my estimation, stems from the fact that WordPress uses absolute URLs throughout its database. So when you link to an element on the site, it is stored as “http://dev.MYCLIENT.com/path/to/element”. When you try to change the site’s hostname, all those links will still point to your development environment. Obviously, this is a very bad thing.

Searching “WordPress absolute URLs” reveals pretty quickly that this is a near-religious topic for some. I don’t want to get into that too deeply, but I still haven’t seen a good argument for why WordPress and its plugins couldn’t store URLs relative to the server root, like “/path/to/element”. This would facilitate moves across hostnames and even moves from HTTP to HTTPS.

At any rate, we’re stuck with this situation, and we need to move a site from one hostname to another. So what can you do?

Many WordPress plugins store their settings in the wp_options table. In addition, you may have links in the wp_postmeta table. You can do a search and replace through those tables, changing links to your old hostname to the new hostname. But there’s a caveat — many plugins will store their values as PHP-serialized objects. A simple search and replace will corrupt those objects, so you need to avoid them. The simplest way to avoid them is to avoid replacing values that contain braces (“{“):

So this will take care of all values that can be safely replaced (simple strings). As for the serialized objects, you can fix them by hand in the database (not recommended, as the formatting of PHP serialized objects is very strict), or you can use the GUI for the plugins in question to update the settings. If you’re using something like Backup Buddy, it will take care of PHP serialized objects as well as simple strings.

Also note that some plugins, like Revolution Slider, use JSON encoding instead of PHP serialization. A search-and-replace would be effective with JSON, but our “WHERE … NOT LIKE” directive in the queries will cause those values to be skipped. So these objects have to be fixed by hand; the nice thing is that it’s easy enough to fix them in the database, since JSON is much more loosely formatted than PHP-serialized objects. Note that BackupBuddy won’t take care of JSON-encoded objects, but if you’ve already used it to take care of PHP serialized objects, you can remove the “WHERE … NOT LIKE” directive from the query, and it will fix simple strings and JSON-encoded objects.

You will also want to update the posts themselves, which may contain hyperlinks within the post content. I also like to change the GUID of the post — another emotionally charged issue in the WordPress community. My rationale for changing the GUIDs is that we built the site in a development environment, so those development pages were never to be viewed by the public or indexed by search engines. The GUID should really reflect the production hostname.

Now there’s one more nasty thing you have to deal with. Some plugins, like Theme Canon’s pagebuilder, store their settings as base-64 encoded binary objects. No search-and-replace strategy will correct those. So you have to load the site on the new host and scour the HTML source for references to the development hostname. If you find them, you’ll have to use the plugin’s GUI inside WordPress to fix the references. This is no easy task if you were not the one who built the site — those page builders that WordPress developers like to use can be convoluted as hell.

If you’re lucky, and you’re not using any plugins that use serialized objects, you can run the four queries I’ve provided, and you’re done. If you have any PHP serialized objects, I recommend using a specialized plugin like Backup Buddy to do most of the heavy lifting for you (and then you just have to deal with JSON-encoded objects and the base-64 BLOBs I mentioned earlier).

I implore the WordPress team to work toward making this process as easy as everything else is inside the WordPress admin UI. I’m wasting tons of time dealing with hostname cleanup when I deploy WordPress sites from development to production.

Leave a Reply

Your email address will not be published. Required fields are marked *