Programmatically Update Settings in Staging

When developing WordPress sites I generally have three environments: live, staging, and local. Since I like my staging environment to be a very close replica of production, I frequently overwrite the database and files in staging. This is especially true when working with a host like WP Engine that has one-click staging environments.

However, when the database is overwritten in staging, there’s a generally a few settings that still need to be different from production. For instance, with WooCommerce sites, I may need to deactivate SSL and put Stripe into testing mode.

Occasionally I’ll also need to deactivate certain analytics plugins or third-party API integrations like MailChimp.

After making these updates manually for months, I finally moved to a programmatic update routine for many of my sites. The code basically just checks which environment we’re in. If it’s not production, it checks if the settings have been updated yet. If not, it makes the updates.

Update Routine Code

Here’s example code for the update routine, which I’ll explain in more detail underneath:

<?php
/**
* Settings to automatically update if we're in a staging environment
*/
function prefix_staging_settings() {
// If we're in production, return early
if ( function_exists( 'is_wpe' ) && is_wpe() ) {
return;
}
// If settings have already been updated, return early
if ( get_transient( 'staging-settings-updated' ) ) {
return;
}
// Get plugins directory
$plugins = plugins_url();
// Deactivate specific plugins
deactivate_plugins( array(
'/chartbeat/chartbeat.php',
'/wpmandrill/wpmandrill.php'
) );
// No SSL in staging
update_option( 'woocommerce_force_ssl_checkout', 'no' );
// Disable REST API in staging
update_option( 'woocommerce_api_enabled', 'no' );
// Use Stripe in test mode
$woocommerce_stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
$woocommerce_stripe_settings['testmode'] = 'yes';
update_option( 'woocommerce_stripe_settings', $woocommerce_stripe_settings );
// If you ever see this in the production log, investigate quick!
error_log( 'Staging settings updated.' );
// Transient is set for one week
set_transient( 'staging-settings-updated', true, ( 60 * 60 * 24 * 7 ) );
}
add_action( 'init', 'prefix_staging_settings' );

Check Environment

In this example the site is hosted with WP Engine. So to check if I’m in a staging environment, I use one of their functions to determine environment (is_wpe()).

Another way to check the environment is by URL. i.e:

if ( 'https://example' == site_url() ) {
     return;
}

Use Transient to Check if Settings Updated

We obviously don’t need the update routine to run constantly, just once after the database has been overwritten. We may even want to re-enable some of those plugins or change a setting back in order to test something specific in staging.

This is where the transient comes into play: get_transient( ‘staging-settings-updated’ ). A transient is basically an option that expires after a specific amount of time. In this case, if the transient has already been set, it means the update routine has run and we don’t need to run it again. For this example, I have the transient expire after a week- but you could set this as long as you like.

Change Settings, De-Active Plugins

This code should be fairly straightforward. For this example I update two WooCommerce options and then a settings from the Stripe extension.

// No SSL in staging
update_option( 'woocommerce_force_ssl_checkout', 'no' );
// Disable REST API in staging
update_option( 'woocommerce_api_enabled', 'no' );
// Use Stripe in test mode
$woocommerce_stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
$woocommerce_stripe_settings['testmode'] = 'yes';
update_option( 'woocommerce_stripe_settings', $woocommerce_stripe_settings );

Logging

It is really important that this code never runs in production. If Stipe switches into test mode on the live site, that could cost a lot of revenue! So, one additional item I added is an item in the log mentioned that the staging settings have been updated. After pushing to production, I can check the logs and make sure that this code wasn’t run accidentally.

About Devin

I'm a WordPress developer based in Austin, Texas. I run a little theme shop called DevPress and work for a startup called Cratejoy. Find me on twitter @devinsays.

5 Responses

  1. Funny, I’ve just started thinking this week about how to automate stuff like this and it was great to see in the “Call for features” for WP4.4 on the Make blog lots of people suggest some kind of environment system.

    It occurs to me that there’s a number of ways to achieve this:

    1) Actual environment variables on the server
    2) Constants in wp-config.php
    3) The options table

    But what I think would be REALLY hand is two things in core. No! Actually, they can be one thing. (I’m thinking on my feet!):

    Environment-specific settings.

    I don’t know how this would work out. Maybe an extra column in wp_options would be best. But I envisage that there is a default environment, and all settings in this default environment take effect unless they are overridden. And then there are specific environments; so if an options entry has an environment specific option then it takes precedence over the default.

    Then you just have a simple constant in wp_config.php that sets the environment.

    I’m sure this isn’t thought through and there will be things like serialised data to take into account, and there will be some kind of UI, but something like this seems like a great concept.

  2. Thanks for sharing your setup, Devin. Automating something like this is a great plan.

    I know there are often lots of ways of solving a problem. It seems the WordPress Pre Option Filter might be another choice and might eliminate the need for a transient.

    Of course a working solution is better than any theoretical idea :)

    Thanks again for sharing.

Leave a Reply