WordPress puts food on my table.

WordPress local dev tips: DB & plugins

Running a WordPress site on your local machine is a great way to do development. I’ve taken advantage of this to do development while on flights (and yes, I realize that in about 5 years it’s going to seem positively quaint that there used to be flights without Internet access).

Today, I’d like to tackle two common issues when running a WordPress site locally:

Handling differing database connection details

Handling plugins that can’t or shouldn’t run on a localhost

My assumptions:

You have your site in a Git repository

You have a working LAMP/MAMP/WAMP/whatever setup.

You already know how to do a mysqldump and import that dump to your local machine

Database connection details

Your database user and password are (or should) be different on your localhost than they are on your production environment. One way to handle this is to have wp-config.php not be in version control and have everyone make their own. Boo. Stop taking things out of version control. Another solution I’ve seen is that people modify the wp-config.php and just try to be really careful not to commit their local changes. Again, boo.

There. Now you can just create a local-config.php file and put your DB_* defines in there. And thanks to the .gitignore addition, you won’t have to worry about accidentally committing your local config.

But what if you want to override other defines locally? Well, just modify them in wp-config.php like so:

if ( !defined( 'SCRIPT_DEBUG' ) )
define( 'SCRIPT_DEBUG', false );

And make sure they’re after the local-config.php block. Now you can override these defines as well.

Plugins that are production-only

I’m a big fan of VaultPress from Automattic. But this is not something you want to run on your localhost. Other backup plugins probably fall into this category of “production-only.”

The bad way to do this is to remember to disable this plugin after you import a DB snapshot to your localhost. Boo. Remember WP_LOCAL_DEV that we set earlier? Let’s use it.

I’ve written a quick “must-use” plugin to handle conditional plugin disabling. Get it here, and put it in the mu-plugins directory (create it in your WP content directory if you don’t already have one).

The part you modify is at the bottom:

new CWS_Disable_Plugins_When_Local_Dev( array( 'vaultpress.php' ) );

I’ve jump-started you by putting vaultpress.php in there. Add plugin filenames to that array as necessary. Don’t forget that most plugins are in a subdirectory, so they’ll be in the form plugin-name/plugin-name.php.

Now those plugins won’t be active when doing local dev (based on the presence of local-config.php).

For a while I’ve been using a switch on $_SERVER['HTTP_HOST'] in wp-config.php. I can’t think of the downsides to it, but seeing this different method touted by much more experienced developers makes me wonder. Are there any gotchas to switching on the hostname?

Depending on how you coded it, it could be potential security issue, if your web server responds to arbitrary host names. But if you do it in a switch, so that the filenames you might be including are effectively hardcoded, that should be fine. That’s similar to what Nikolay is doing above, except he’s also supporting regular expression matches.

Mark, sorry to come back to this, just want to clarify. I use a switch on $_SERVER['HTTP_HOST'] in wp-config.php, but I’m basically just defining the constants with different values in each case (I’m not including any files). I’m assuming the vulnerability you’re talking about would only arise if I was passing $_SERVER['HTTP_HOST'] through to an include or require statement? Or am I missing an aspect of include vulnerabilities here?

Mark, I’m about to do a talk at WordCamp UK, and I’ll be discussing this kind of technique there. I’d love to get word from you on my previous query (comment from June 30th) so I can be sure about the security (or otherwise) of the technique I mentioned. Thanks!

I’ve got my production wp-config up a level on my ftp and dev, while I keep my local wp-config in its default location. On the local it finds the first copy and ignores the production. This works out for me as I can still edit both without conflict (as long as I don’t upload the local config accidentally).

I have used svn for years and am just getting started with git. Can you recommend a good explanation of how to setup git, so that it tracks one of the official (svn) repositories for WP itself as well as the standard plugins, which I shouldn’t be editing, while giving me a local editable version of my own themes and plugins on the development site with a way to roll them out to the production one. I’m sure there must be a pretty standard way to set all that up, but I can’t find a good explanation. p.s., Good meeting you at WordCamp Phoenix and I was impressed with the professionalism and enthusiasm of all the core team, too.

• WordPress can be installed in a subdirectory.
• wp-config.php can exist “a level up” from the WordPress directory.
• The WordPress content directory (normally wp-content) can be moved, so that it does not exist within the WordPress directory.

Put these three things together, and you can create a setup with a completely-unmodified WordPress directory, as I have done above.

(The space between http:// and the rest of the URL shouldn’t be there… WordPress.com is trying to autolink the URL and mangling it)

And then on the server, I do a deploy (using Capistrano). Note that the --all switch for git tells it to remove files that have gone away. That’s why I delete the wordpress directory first.

There is one downside to this setup. Well, two. First, setting it up is more complicated. Of particular annoyance is how you have to specify your uploads directory using a relative path (relative from wp-content). And you have to set some defines in wp-config.php (more info). Second, some plugins won’t work. If they hardcode wp-content anywhere in their code, they won’t work. This is becoming less and less of a problem, but you still run in to it occasionally.

As an alternative, you can set it up like this:

/wp-config.php
/wordpress/

In this setup, everything mutable lives in /wordpress/wp-content/, like normal. When you want to upgrade WordPress, do:

I set mine up just like you said with /wordpress, /blog-content (not always called this), wp-config.php, the optional local-config.php, and index.php all in the root directory. Then I actually have a bash script that updates wp:

And thanks to the .gitignore addition, you won’t have to worry about accidentally committing your local config.

🙂

One thing I’ve done in the past is crazily parse/eval wp-config-sample.php as my “local-config.php” since that file is always in the repo. Plus, having a local DB with the sample connection details makes spinning up new sites really easy.

If you want your local config to be portable, you could check it in, and then use the presence of a .localdev file (git ignored, of course) to trigger its use.

Of course, that forces everyone who develops on the site to use the same host/db/user/pass on their local machines. I have sites where I’m not the only contractor, and I don’t want to presume to dictate other people’s local setups.

Cool to see what other people are doing here. I used the switch/include method when I was working on Magento a lot, since their configs are stored in xml files instead of php files.

We use environment variables for credentials like this, including things like Amazon S3 keys. That way the config can move from environment to environment and get committed to version control with impunity. It also keeps the credentials out of the hands of 3rd parties — contractors — when we have other people work on our code.

I have a draft on my blog where I talk more about it, perhaps you’ve just inspired me to finish it up. Another thing we do is, when on a development environment we filter all the content to replace urls dynamically. This changes the production URLs to development URLs (e.g., http://www.example.com -> local.example.com). This makes it easy to pull a database snapshot from the live site, load it into a dev environment, and just have it work. It’s been great to use.

Then, when I deploy it, via capistrano (ex: cap deploy dev) then this copy to a temporary folder, replaces the files (wp-config.php…) with parameters from the dev environment that is in the yaml file.🙂

Great post and Tips for developing locally 2 things to add, 1 of which I haven’t done, but maybe you have.

1. WP has a check in the background the tries to connect to the internet (I’m assuming an auto update check), but if your not connected to the internet you get an error. I’ve been meaning to add check where if I’m not connected to the internet don’t bother trying.

2. Have you used WP+Networking+Domain mapping for local development? I’ve been using it, deploying sites and loving it.

Thanks Mark! These tips are really helping in my 100th iteration of local development.

I absolutely love the flow you have set up for upgrading wordpress … I’ve been really struggling with how to implement both html5 boilerplate and wordpress into my base startup projects, while maintaining the ability to easily diff and update boilerplate, and upgrade wordpress … I’m drooling at the idea of being able to use your method, BUT, my local dev is multisite with subdomains, so, there is no wp in a directory option.

Might you have any slick moves that would assist in this particular setup???😉

Currently I’ve just ended up setting up a remote tracking branch for both and pulling them in, hoping in the future to be able to just do a straight fetch merge on core wordpress and a fetch diff merge on boilerplate to accept or reject changes as they apply to my customized version.

Sad setup I know, but, after running around the office like a crazed monkey for the past month … getting deeper and deeper into the rabbit hole …

Thanks! I just got this up and running and finally can auto-disable W3TC on my local install. This is a huge help to making my local workflow smoother.

It would make more sense to me however to define the plugins one wants to disable in the local-config.php file rather than modifying the plugin for each plugin one wants to disable. This way the plugin would be the same on every site and I’d just have to tweak local-config.php. Is that scenario even possible?

Thanks for the awesome article. It helped me out a lot. This has been a lot more work than what I thought it was going to be, but it has been worth learning every bit of it. I bookmarked your site and I am going to share it with others people I know that want to run host their own site or would like to learn more.

Benefit’s Love Your Look makeup to match your lifestyle collection takes the guesswork out of gorgeous. Choose from three unique looks: The Lana light neutral shades, The Gabbi medium neutral shades, and The Betty deep neutral shades. Go for a “lifestyle look” or, be daring and mix and match! All of the beautiful shades for lips, eyes, and cheeks will get you the look you want! You’ll love the hidden surprise, a “beauty fortune” inside every package.

For my reference: can anyone explain why using “option_active_plugins” in the functions.php file with a simple/similar callback function to the mu-plugin above does not work. However when run from the mu-plugins folder it works perfectly?

Because plugins are loaded BEFORE the functions.php file is loaded, which means your code isn’t being processed until after that option has already been retrieved and used. MU plugins are loaded BEFORE regular plugins. Rough order for you up through ‘init’ action:
* MU Plugins loaded
* Constants (cookie and SSL) set up
* Plugins loaded
* Pluggable files loaded
* Global query set up
* Rewrites set up
* Locale loaded
* Theme set up (functions.php included)
* WP initialized
* Fire ‘init’ action

This is all great and I use something similar for a local -> staging -> production environment. All php require a local wp-config-local.php with environment specific info.

What’s got me stymied though, is how to keep the content in the DB’s in sync- I periodically dump from production down to the other environments, but it’s a chore. It would be great to be able to stage changes for client review/approval on the staging server (including perhaps DB & content changes) then turnkey push said updates to production.

Ask a WordPress Dev

Do you have an interesting WordPress-related question? Submit your questions, and I'll periodically pick the best one and answer it here on my blog! It can be anything from usage tips to hardcore WP development questions.