My WordPress Workflow

12 comments Posted in WordPress

The subject of WordPress workflows has been rife on Twitter today, and as a hardened WP developer, I thought I should chime in and share my optimal workflow.

In this little writeup I’ll show you how to:

  • Handle multiple URLS
  • Support for dev, staging & live databases
  • Source control
  • Deploying scripts

Before I get started, I just want to say that I’ll gloss over anything that isn’t WordPress specific. No particulars in version control or deployment scripts, just the bits that make it possible in WordPress.

I’ll assume this follows the 3 tiered development platform, meaning a local version for development, a staging server for showing the work to the client and the live version which the world sees.

Getting Started

So, when I start a project, the first things I do are set up a new source control repo and choose a local domain inside MAMP Pro. We’ll give this site a local domain of mysite.dev, though that’s not important.

The next step is to download WordPress and chuck it in the appropriate place. The next step is a huge time saver. It means your install will work with any domain, no matter where it is, be it local, staging or live. This goes in wp-config.php just before the comment that says /* That's all, stop editing! Happy blogging. */.

// Assuming WP is in the root folder, adjust if not
define('WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST']);
define('WP_HOME', 'http://' . $_SERVER['HTTP_HOST']);
define('WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/wp-content');

Databases

WordPress is just PHP framework. There’s nothing you cannot do in it that you can do outside of it. So, using regular PHP if/else statements, we can make WP work with different databases, depending on the URL.

In wp-config.php, find the DB definitions.

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress.dev');

/** MySQL database username */
define('DB_USER', 'root');

/** MySQL database password */
define('DB_PASSWORD', 'root');

/** MySQL hostname */
define('DB_HOST', 'localhost');

Replace the whole lot with the code below. I’ll comment it properly so you know what it’s doing.

$domain = $_SERVER[HTTP_HOST];

if ($domain === '') : // If is live enviroment
    define('DB_NAME', 'our_live_db');
    define('DB_USER', 'our_live_user');
    define('DB_PASSWORD', 'our_live_password');
    define('DB_HOST', 'localhost');
elseif () : // If is staging enviroment
    define('DB_NAME', 'our_staging_db');
    define('DB_USER', 'our_staging_user');
    define('DB_PASSWORD', 'our_staging_password');
    define('DB_HOST', 'localhost');
elseif () : // If is first developers local enviroment
    define('DB_NAME', 'first_env_db');
    define('DB_USER', 'first_env_user');
    define('DB_PASSWORD', 'first__env_password');
    define('DB_HOST', 'localhost');
elseif () : // If is second developers local enviroment
    define('DB_NAME', 'second_env_db');
    define('DB_USER', 'second_env_user');
    define('DB_PASSWORD', 'second__env_password');
    define('DB_HOST', 'localhost');
else () : // If none, fallback to these
    define('DB_NAME', 'fallback_db');
    define('DB_USER', 'fallback_user'); // Usually 'root'
    define('DB_PASSWORD', 'fallback_password'); // Usually 'root' too
    define('DB_HOST', 'localhost');
endif;

With those if/else statements, you could make the database side of things work any way you want. You could just have the live environment then have everyone else (meaning every developer and staging environment) linked up to the staging database. That little snippet I mentioned earlier means domain & database issues just don’t exist, so long as you never hard-code a URL in, which is bad practice anyway.

Source Control

I check in code as much as I can, I recommend you to too. Make sure the wp-config.php is in source control too, or at least make sure it’s the same file across every developers system, as well as live & staging environments.

Deployment

I currently use Beanstalk to host my SCM repos. They have a nice feature that deploys sites via (S)/FTP, be it the staging or live environment. They can even handle multiple servers, so if you have a load-balanced setup with multiple servers (without a replication script), you can deploy the code to each of those servers.

Closing…

Hopefully these small tips mean you can work with WP across multiple environments with multiple developers. I’ve used this system on a site with 12 developers before, so I know it works.

Let me know if you have any tips, additions or changes.


Update [03/09/12 @ 12:25pm]

I’m digging up a few solutions and fixes to help with absolute asset URLs. I’ll post them here when I’m done.

Twelve comments

  1. MrQwest # September 3rd, 2012 at 2:27 pm

    Nice work Paul. Some nice tips and tricks hidden away in there.

    One quick question though, the chunk of code you’ve posted about defining URLs right up the top so the site works regardless of domains, where does that code go? I’m no WP expert (as you know) but I can see how useful it’d be :)

    • pauladamdavis # September 3rd, 2012 at 2:45 pm

      Damn. Can’t believe I missed that bit! I just added where it goes to that section.

  2. Luke Peters # September 3rd, 2012 at 3:19 pm

    Great post, man! I don’t do too much with WordPress lately, but I still took away some useful bits :)

  3. Vincent # December 22nd, 2012 at 1:51 pm

    Hi Paul,

    I have added in your code for defining the different database using the if/else statements, but I am getting a parse error on the first elseif statement. I am using WordPress 3.5 not sure if that would make a difference?

    Thanks!

    • pauladamdavis # December 22nd, 2012 at 2:05 pm

      Hi Vincent, can you share your code in. Gist of Pastebin?

    • pauladamdavis # December 23rd, 2012 at 4:00 pm

      Ah, I see the issue. I didnt add any clauses to the if/else statements. So The lines 19,24,29,34 & 39 need a clause in the brackets, such as if ($domain === 'mylivesite.com' and elseif ($domain === 'devsite.dev').

  4. Nick # January 13th, 2013 at 8:43 am

    Wouldn’t this be bad practice? Not only could other devs but the client themselves and anyone who has access to this folder at any point could pull down this global wp-config file with direct access to MULTIPLE databases. Am I missing something?

    • pauladamdavis # January 13th, 2013 at 4:32 pm

      You are correct, but I guess it depends on the workflow. I much prefer to have the files on multiple servers to be exactly the same. I’ve never had a problem with files being breached, but having a different wp-config.php file on each server isn’t a problem, just make sure it’s not included in the SCM repo.

  5. Tony # April 19th, 2013 at 2:41 am

    I agree with Nick. I lean toward security over convenience. Anyone who has access to your computer (or if your laptop gets stolen) will have access to all of your databases. It is not something that happens all the time but I would be cautious about it. Just a thought.

    I normally set up wp-config.php separate for each environment. I then use .gitignore (or any comparable thingy :) in your VCS) to exclude such files as wp-config.php and .htaccess out of my repo just to be safe.

    Despite that, very good tips. Thank you.

Leave a Reply