
WordPress Deployments: Example of Database Changes in Code
How do you update the database of a WordPress site that's already in production without a lengthy content freeze or losing your client's data? If you've searched the Metal Toad blog, and who among us hasn't, you know from an earlier post by Chris Svajlenka that you should make any changes to the WordPress database via code; code that you can version control, code that you can deploy, code that you can reproduce.
That sounds like great advice, but what if you don't know how? There's a plugin for that, but it's not what you think. It's not an official WordPress hosted plugin that you download. It's an example of a plugin written by Andy Mantell that you write and modify to deploy your database changes in code. Why write a blog post about somebody else's plugin? Because it worked on the first try, it's easy to modify, and it wasn't easy to find.
Here's a reprint of Andy's code that just worked.
/* Plugin Name: Deployment routines Description: Runs update routines allowing code based database updates. Author: Andy Mantell Version: 1.0 */ add_action( 'admin_init', 'deployment_admin_init' ); /** * Attached to init. Runs any necessary update routines */ function deployment_admin_init() { // What is the current version of this plugin? $deployment_version = 1; // What is the current version in the db $db_version = get_option( 'deployment_version', 0 ); // Is the db out of date? if ( $db_version < $deployment_version ) { // If so, loop over all subsequent version numbers and attempt to run corresponding deployment_update_N functions for ( $version = $db_version + 1; $version <= $deployment_version; $version ++ ) { if ( function_exists( 'deployment_update_' . $version ) ) { $success = call_user_func( 'deployment_update_' . $version ); // If the function returns a boolean false, log an error and bail out. Subsequent updates may rely on this update // so we shouldn't proceed any further. if ( $success === FALSE ) { // @TODO: log error here break; } } // If we've reached this far without error, update the db version update_option( 'deployment_version', $version ); } // @TODO: output update summary on success } } /** * Update functions. */ /** * Disable the wordpress-meta-description plugin. * Enable and configure the add-meta-tags plugin */ function deployment_update_1() { // Include the plugin.php file so you have access to the activate_plugin() function require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); deactivate_plugins( WP_PLUGIN_DIR . '/wordpress-meta-description/wp-meta-description.php' ); activate_plugins( WP_PLUGIN_DIR . '/add-meta-tags/add-meta-tags.php' ); update_option( 'add_meta_tags_opts', array( 'settings_version' => 2, 'site_description' => 'Site description here', 'site_keywords' => 'site, keywords, here', 'global_keywords' => 'global, keywords, here', 'site_wide_meta' => '', 'auto_description' => '1', 'auto_keywords' => '1', 'auto_opengraph' => '0', 'auto_dublincore' => '0', 'noodp_description' => '0', 'noindex_search_results' => '1', 'noindex_date_archives' => '0', 'noindex_category_archives' => '0', 'noindex_tag_archives' => '0', 'noindex_author_archives' => '0', 'copyright_url' => '', 'default_image_url' => '', 'i_have_donated' => '0', ) ); return TRUE; }
Modify Options
To demonstrate the ease of modifying this plugin, I'll use my plugin to change a couple options, add a new user, and create a table.
/* Plugin Name: MTM WordPress Deployment Updates Description: Runs update routines allowing code based database updates. Author: Metal Toad Media Version: 1.0 */ add_action( 'admin_init', 'deployment_admin_init' ); /** * Attached to init. Runs any necessary update routines */ function deployment_admin_init() { // What is the current version of this plugin? $deployment_version = 3; // What is the current version in the db $db_version = get_option( 'deployment_version', 0 ); // Is the db out of date? if ( $db_version < $deployment_version ) { // If so, loop over all subsequent version numbers and attempt to run corresponding deployment_update_N functions for ( $version = $db_version + 1; $version <= $deployment_version; $version ++ ) { if ( function_exists( 'deployment_update_' . $version ) ) { $success = call_user_func( 'deployment_update_' . $version ); // If the function returns a boolean false, log an error and bail out. Subsequent updates may rely on this update // so we shouldn't proceed any further. if ( $success === FALSE ) { // @TODO: log error here break; } } // If we've reached this far without error, update the db version update_option( 'deployment_version', $version ); } // @TODO: output update summary on success } } /** * Update functions. */ /** * Disable the wordpress-meta-description plugin. * Enable and configure the add-meta-tags plugin */ function deployment_update_1() { // Include the plugin.php file so you have access to the activate_plugin() function require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); deactivate_plugins( WP_PLUGIN_DIR . '/wordpress-meta-description/wp-meta-description.php' ); activate_plugins( WP_PLUGIN_DIR . '/add-meta-tags/add-meta-tags.php' ); update_option( 'add_meta_tags_opts', array( 'settings_version' => 2, 'site_description' => 'Metal Toad Media', 'site_keywords' => 'Phylum: Chordata, Kingdom: Animalia, Class: Amphibia', 'global_keywords' => 'boreal, arroyo, amargosa', 'site_wide_meta' => '', 'auto_description' => '1', 'auto_keywords' => '1', 'auto_opengraph' => '0', 'auto_dublincore' => '0', 'noodp_description' => '0', 'noindex_search_results' => '1', 'noindex_date_archives' => '0', 'noindex_category_archives' => '0', 'noindex_tag_archives' => '0', 'noindex_author_archives' => '0', 'copyright_url' => '', 'default_image_url' => '', 'i_have_donated' => '0', ) ); return TRUE; } // Add another user function deployment_update_2() { wp_create_user( 'trevor', 'thefr0g', 'trevor@nospam.dev' ); return TRUE; } // Add table to the database // https://codex.wordpress.org/Creating_Tables_with_Plugins function deployment_update_3() { global $mtm_db_version; $mtm_db_version = '1.0'; global $wpdb; global $mtm_db_version; $table_name = $wpdb->prefix . 'mtm_toads'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, name tinytext NOT NULL, text text NOT NULL, url varchar(55) DEFAULT '' NOT NULL, UNIQUE KEY id (id) ) $charset_collate;"; require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); dbDelta( $sql ); add_option( 'mtm_db_version', $mtm_db_version ); }
Now it's your turn. What WordPress databases changes will you write in code?
Comments
Great post, Monika!
Inspired me to implement a command line interface (through wp-cli) for my plugin project, Add-Meta-Tags, in the hope that it could be useful in cases of remote deployment/maintenance of WordPress web sites.
Thanks for writing it!
George
Wed, 11/18/2015 - 12:29