Wordpress Merge Content Uploads From Monthly to Single Folder How
Database synchronization is a problem that still gets raised almost every calendar month in the local WordPress communities I'thousand part of – "if I am making changes to my local site, what happens to any updates fabricated on the live site, if I push my local database back to live?"
First #WordPress Meetup in ix months, start person I speak to, first trouble they speak about: database merging 😬
— Iain Poulson (@polevaultweb) June 28, 2018
With WordPress officially becoming an developed, is this not something nosotros should have solved by at present? Has anything changed since Brad spoke about this problem at WordCamp Miami in 2014? In this post, I'll revisit the problem, expect at what options you have, share how we deal with it for our sites, and review the off-the-shelf options that exist.
What is the Problem?
It's an event that exists for almost whatsoever developer working on a local development copy of a WordPress site that as well has a alive version running. The developer makes changes locally, configuring theme settings, calculation new pages, adding Advanced Custom Fields, tweaking plugin options, etc. Meanwhile, the alive version is nether constant change. Either past the client, perhaps writing new blog posts, or in the case of ecommerce sites, adding new products, or by customers placing orders. When the developer is prepare to button their local changes to the alive site, at that place is a chance they will overwrite whatever changes on the alive site. It's a problem that affects all database-driven content management systems and is one of the trickiest parts of WordPress site development. As information technology stands, there is no easy way to reconcile these changes with a nice simple merge.
Ugh… I hate merging database changes between evolution environment and production. #wordpress #dba #devlife
— Shawn Hooper (@ShawnHooper) Jan 4, 2015
When Workarounds Won't Work
For straightforward brochure or marketing sites, data merging and conflict resolution aren't needed. During any development cycles, the data on the alive site remains largely unchanged. Copying over whatever new media files and a partial push of the tables in the MySQL database with changes, using a plugin similar WP Migrate DB Pro, would be sufficient. With more circuitous sites, the data architecture WordPress uses (and encourages developers to use) makes it extremely difficult to perform selective data migrations.
For example, in ecommerce stores where the only data changing on the live site is the products past the shop owners and the orders from customers, a partial data migration should work in theory. Ideally, the data tables that store these pieces of data could be ignored when pushing other data changes made during site development. With WordPress, in that location's simply one problem – custom post types.
Why Custom Posts Types Complicate the Problem
WordPress has an extremely flexible data structure that allows information objects of unlike types to exist stored in the wp_posts
table. The different data objects are known as custom post types and their blazon is defined past the post_type
column in the wp_posts
table. This isn't the almost intuitive name for the table that holds records of data for non only posts, merely also pages, menus, attachments, revisions, card items, and any custom data object registered every bit a custom post type. Recollect 'house' for a real estate site, 'animal' for an creature rescue site, or merely 'physician' for the documentation part of a product site.
When custom post types landed in WordPress 3.0, there was much rejoicing at a feature which enabled WordPress installations to become more than only blogs. However, I believe that custom post types, and their information model implementation, have become detrimental to the WordPress ecosystem.
On the one hand, this is a beautifully uncomplicated and flexible system, with a simple PHP API to register new data objects with merely a few lines of code. When you register a custom post type, you get a lot of functionality for free without having to lawmaking it yourself; a new menu option, simple CRUD management of the objects, a table interface for listing and majority actions, and even REST API endpoints.
On the other hand, the ease of registering new types ways that sometimes the wrong kind of data objects are being stored in this way. Like my earlier example of ecommerce products and orders – the most critical of information for a store owner is kept in the same table as all the other post types. The live site will continue to get new records added to wp_posts
as new orders are created. If any changes are fabricated to posts or pages on the local site, the wp_posts
tabular array can no longer be pushed back to alive without losing those orders!
Custom post types can also create other issues for a WordPress site. Using them to store every type of data can cause functioning problems. WordPress will continually query the wp_posts
table when displaying posts, pages, and other post types on the forepart end of the site, and equally that table grows, the slower those queries become. Of course caching can aid, merely better intendance should be given to deciding where to store data that could potentially grow to a large size.
For case, Easy Digital Downloads currently registers a post type of 'edd_log,' which records every time an particular is downloaded. The log record is really a piece of transactional data that should take its own table, as information technology could potentially scale to a huge number of rows that are unnecessary in the wp_posts
tabular array. I've seen this happen first hand:
To say I'm excited about @eddwp Easy Digital Downloads three.0 is an understatement!
It will replace custom postal service types in favour of custom database tables and hopefully claw back some performance improvements on my site. pic.twitter.com/IMVaeRs2UR
— Iain Poulson (@polevaultweb) May 16, 2019
Thankfully plugin shops are aware of these bug and are changing their arroyo.
WooCommerce has been working on migrating product and production meta to custom tables since 2016. Their work to drift orders to its own table appeared to stall in 2018, merely they announced an official program for a custom order table earlier this yr. There is currently no ETA for when this will be implemented, but anyone interested can follow the GitHub project lath.
The EDD team is working on their big iii.0 update, which will completely migrate all their custom post types to custom tables. John James Jacoby (JJJ) spoke at WordCamp Europe 2019 about a new approach to managing and accessing custom tables. All the same, EDD 3.0 is notwithstanding in public beta and is non withal ready for production sites.
Of course, while these improvements aid, they volition never fully ready the database merging event. Ignoring sure tables from a database migration will but get you then far. Most of the time, alive sites are irresolute in such a fashion that any changes to a development site cannot exist automatically merged back in, and that'south where the manual approach is probably withal the all-time.
What Alternatives Do You Have?
This was the realization we came to when we congenital the now-retired Mergebot. For every plugin or theme that writes to the database, you need to know how it stores its information so you lot can correctly handle IDs and conflicts. Trying to resolve all these conflicts ends upward being very complex. Fifty-fifty with a solution that supports all major plugins and themes, developers would withal need to manually configure unsupported plugins/themes, which is ofttimes more of a hurting than the database deployment problem itself. If you simply had to do this once, it wouldn't be then bad, merely every fourth dimension a plugin or theme is updated, it could change the way it stores data. Information technology's a huge hassle that never ends.
There are a few means to mitigate these conflicts.
SQL Scripts
I solution is to record any data changes as SQL scripts on your local development environment. Allow's look at a simple example. Installing WooCommerce requires you lot to create a few pages, for case, the checkout and my account pages. Every bit shortly as these pages accept been created, you could export the information from the database to create an SQL file that includes the queries used to create these pages:
INSERT INTO `wp_posts` (`ID`, `post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_title`, `post_excerpt`, `post_status`, `comment_status`, `ping_status`, `post_password`, `post_name`, `to_ping`, `pinged`, `post_modified`, `post_modified_gmt`, `post_content_filtered`, `post_parent`, `guid`, `menu_order`, `post_type`, `post_mime_type`, `comment_count`) VALUES (NULL, 1, '2013-02-27 21:03:thirteen', '2013-02-28 01:03:13', '[woocommerce_checkout]', 'Checkout', '', 'publish', 'closed', 'closed', '', 'checkout', '', '', '2013-11-04 09:52:sixteen', '2013-11-04 13:52:16', '', 0, 'http://yourwebsite.com/checkout/', 0, 'page', '', 0), (Aught, ane, '2013-02-27 21:03:13', '2013-02-28 01:03:thirteen', '[woocommerce_my_account]', 'My Account', '', 'publish', 'closed', 'closed', '', 'my-account', '', '', '2013-11-04 09:52:50', '2013-xi-04 13:52:fifty', '', 0, 'http://yourwebsite.com/my-business relationship/', 0, 'page', '', 0);
Once you lot're gear up to deploy your changes, import your SQL scripts into the production database, and you lot're set up to become.
PHP Scripts
Instead of recording the SQL queries subsequently, y'all could instead write a PHP script that creates the data. Of form, y'all can include SQL queries in there equally well, simply you can likewise do a lot more. Let'south use the scenario above once more as an instance, but instead, I'll write a function to deploy the changes.
/* * To run the deployment * 1. Log in as an administrator * 2. Go to http://hellfish.media/?deploy_changes=ane */ add_action( 'template_redirect', 'deploy_changes' ); function deploy_changes() { // If the request is not our deployment if ( !isset( $_GET['deploy_changes'] ) ) { return; } // Simply allow a logged in admin to run the deployment if ( !current_user_can( 'install_themes' ) ) { repeat 'Not logged in.'; exit; } // Run script for 5 mins max set_time_limit(60*five); $pages = assortment( assortment( 'content' => '[woocommerce_checkout]', 'championship' => 'Checkout' ), array( 'content' => '[woocommerce_my_account]', 'championship' => 'My Business relationship' ) ); foreach ( $pages every bit $page ) { $new_page = array( 'post_type' => 'page', 'post_title' => $page['title'], 'post_content' => $page['content'], ); wp_insert_post( $new_page ); } echo 'Deployment complete.'; exit; }
You could put this code in a custom maintenance.php
file and include that from the functions.php
file in your theme, or add it every bit a custom WordPress plugin rather than include it in the theme, simply either way works. One time you're ready to deploy, push button this code to your live site and log in every bit an admin. So run the lawmaking by appending the deploy_changes
query cord to the finish of your domain, for example:
http://hellfish.media/?deploy_changes=1
Afterward you've made the changes, remove the function from the file (or disable the plugin) to make certain yous don't rerun the deployment accidentally. Source control (like Git) ensures that you always continue a history of the one-time deployment code if you lot ever demand information technology once again.
You lot tin can have this a step further. In a custom plugin, you could store a version number for the plugin in the database and merely run specific changes depending on the version number. That way, you just have to add together new lawmaking which runs based on the version number and update the version number later each department of lawmaking is run. Let's aggrandize the above example to include a new page using this version check method.
/* * To run the deployment * 1. Log in as an administrator * 2. Go to http://hellfish.media/?deploy_changes=one */ add_action( 'template_redirect', 'deploy_changes' ); office deploy_changes() { // If the asking is non our deployment if ( ! isset( $_GET['deploy_changes'] ) ) { return; } // Simply allow a logged in admin to run the deployment if ( ! current_user_can( 'install_themes' ) ) { echo 'Not logged in.'; go out; } // Run script for 5 mins max set_time_limit( 60 * 5 ); // get the version number class the wp_options table, or default to 0 $version = get_option( 'hellfish_custom_plugin_version', '0' ); // simply run if the $version is 0 if ( version_compare( $version, '0', '=' ) ) { $pages = array( array( 'content' => '[woocommerce_checkout]', 'championship' => 'Checkout' ), array( 'content' => '[woocommerce_my_account]', 'championship' => 'My Account' ) ); deploy_pages( $pages ); // update the version stored in the wp_options table update_option( 'hellfish_custom_plugin_version', 'ane' ); echo 'Deployment complete.'; exit; } // only run if the $version is i if ( version_compare( get_bloginfo( 'version' ), '1', '=' ) ) { $pages = array( array( 'content' => '[woocommerce_cart]', 'title' => 'Cart' ) ); deploy_pages( $pages ); update_option( 'hellfish_custom_plugin_version', '2' ); echo 'Deployment complete.'; } } // deploy any pages set upwards in the deploy_changes function function deploy_pages( $pages ) { foreach ( $pages as $page ) { $new_page = array( 'post_type' => 'page', 'post_title' => $page['title'], 'post_content' => $page['content'], ); wp_insert_post( $new_page ); } }
Building this as office of a custom plugin means you can link any database updates that may be required to the plugin version number that you lot update with every plugin release.
What We Do
Essentially, we're using a similar approach hither at Delicious Brains, only I've added a fleck more control and process to information technology. Inspired by Laravel's database migrations and seeding system, I've created a migrations library that helps me write scripts to make table and data changes during evolution. There's a fair bit of overlap here to JJJ's work equally well as the existing wp-table-migrations package, but I wanted something custom that can be used across our sites; deliciousbrains.com and spinupwp.com.
This is the process:
- Create a new migration grade file that contains the code to add/edit/delete a table, also as inserting/updating/deleting data from the database
- Each migration file, once run, will be recorded in a
migrations
table to ensure it isn't run once again - This file can be committed to Git as part of a characteristic branch
- The deployment procedure for the live site has a build step subsequently the files are copied to the server to run the database migrations via a custom
wp dbi migrate
WP-CLI control
This allows me to write PHP code to change tables and alter information every bit part of any code changes for a new feature or bug ready. Those changes are stored in Git and form function of the GitHub pull request that is reviewed, merged, and eventually deployed. Using this process does hateful I demand to be enlightened of how WordPress code alters the database and then that I can make schema changes using code like this:
<?php namespace DeliciousBrains\WPMigrations\Database\Migrations; apply DeliciousBrains\WPMigrations\Database\AbstractMigration; class ComposerStatsTable extends AbstractMigration { public function run() { global $wpdb; $sql = " CREATE TABLE " . $wpdb->prefix . "woocommerce_software_composer_download_statistics ( id bigint(xx) NOT NULL auto_increment, composer_key varchar(50) Not NULL, package varchar(50) NOT Nix, version varchar(16) NOT NULL, original_package varchar(fifty) NOT Nix, download_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL, Principal KEY (id) ) {$this->get_collation()}; "; dbDelta( $sql ); } }
As well as making changes to the data like this:
<?php namespace DeliciousBrains\WPMigrations\Database\Migrations; use DeliciousBrains\WPMigrations\Database\AbstractMigration; form AddWpSesLandingPage extends AbstractMigration { public function run() { $page_id = wp_insert_post( array( 'post_title' => 'WP SES is Now WP Offload SES Lite', 'post_status' => 'publish', 'post_name' => 'wp-ses-now-wp-offload-ses-lite', 'post_type' => 'page', 'post_parent' => 49760, ) ); update_post_meta( $page_id, '_wp_page_template', 'folio-wp-ses-landing.php' ); update_post_meta( $page_id, '_yoast_wpseo_metadesc', 'Looking for WP-SES.com? WP SES is now WP Offload SES Calorie-free. Come across what improvements we\'ve made to the free version and what you can become when you upgrade.' ); } }
I'thousand using WordPress PHP code to script any database changes manually, which can be tested using wp dbi drift
on the command line. I tin also roll back the last migration if I include any rollback lawmaking in the rollback
method of the migration class. I'chiliad in control of the changes I make to the database with scripting similar this, simply sometimes I do wish I could use the WordPress admin UI to make my changes and perform a merge, similar we hoped would be possible with Mergebot.
What nigh other merging solutions on the market?
Honorable Mention: VersionPress
When we started working on Mergebot, a like plugin existed that used Git to rails changes to WordPress files and the database called VersionPress.
Unfortunately, in June 2020, the development team appear that development of VersionPress had come to an end.
WPMerge
Not long afterwards we decided to shut Mergebot down, a new merging solution entered beta. WPMerge is similar to how Mergebot worked in many ways. You brand sure your development database is synced with live, beginning recording, and then make changes to your evolution site to exist practical subsequently to live.
Old afterwards its launch, WPMerge partnered with Nexcess to add further value to their WordPress and WooCommerce hosting customers.
I gave WPMerge a quick road test, and it worked well. I did detect some differences from Mergebot in its implementation. It uses database triggers on the development site's database to record all the queries executed instead of recording them using the WordPress 'query' filter.
In my brief testing, I did the following:
- Adding a new postal service to dev and making certain when it was deployed to the live site it had the right mail meta relationship with the deployed mail service ID
- Adding a new post with a gallery of newly uploaded images to see if the media post IDs in the gallery shortcode added to the postal service content were correctly replaced on deployment – they were 🎉
- Editing an existing mail title on my development site and deploying to live where the title had also changed – the development edit was used without asking 😬
Unfortunately, WPMerge also doesn't handle conflict resolution:
For now, but like Git, the development changes accept priority. We are looking to develop a conflict resolution module where you can choose which changes to go on.
For instance, suppose you lot alter a page title from 'About' to 'About U.s.' on your development environment, just earlier you deploy the changes, your client has also changed the title from 'Virtually' to something else similar 'The Squad'. In that case, WPMerge will ignore the customer's change and apply your alter every bit the new value.
Even every bit a developer on a old competitor, I was impressed with WPMerge and how information technology worked out of the box. I do think the UI/UX could do with some smooth to make information technology easier for developers to use and understand the workflow amend. I institute myself very confused as to what the right activeness was to apply my current development changes to the alive surroundings. I also noticed only how many queries were recorded and deployed that were unnecessary for the changes I was making. After the uncomplicated circular of testing I described above, the plugin was recording over 400 queries! This made me nervous virtually using this on big-scale sites with lots of plugins installed.
While WPMerge is still in active evolution, it doesn't seem to exist adding whatsoever new features too the cadre offering. The latest changelog entries reverberate only a few issues fixes and an update for PHP eight support.
Wrapping Up
I even so don't believe there is a magic bullet solution for database merging in WordPress. It is a problem that developers need to exist aware of and so they don't get themselves into a situation with out-of-sync local and live databases. Be prepared before you make changes, tape what yous do and and then play those changes back afterwards at deployment time. For me, keeping this process as systematic and automatic as possible is central to improving my development workflow. It likewise reduces man error, specially in a team environment, as every data change is committed to version command.
What is your preferred method of applying development database changes to a alive site? Have you lot institute a tool to perform database merging that you lot are happy with? Allow us know in the comments.
Source: https://deliciousbrains.com/syncing-wordpress-database-changes-merging/
0 Response to "Wordpress Merge Content Uploads From Monthly to Single Folder How"
Post a Comment