Was ist der einfachste Weg, um kaskadierende database-Upgrades für mein Plugin zu implementieren?

Nehmen wir folgende Situation an:

Ich entwickle ein Plugin. Das Plugin benötigt eine benutzerdefinierte databasetabelle, um bestimmte Informationen zu speichern.

Von Monat zu Monat veröffentliche ich neue Versionen meines Plugins. Verschiedene Versionen können ihre eigenen Sätze von Änderungen der Tabellenstruktur und der Daten der Tabelle haben. Zum Beispiel:

  • Version 1.0.0 hat eine Ersteinrichtung für die Tabellenstruktur
  • Version 1.1.0 hat Änderungen an einem Spaltentyp und erfordert eine Aktualisierung der Daten dieser Spalte
  • Version 2.0.0 erfordert das Erstellen von zwei neuen Spalten, das Aufteilen von Daten aus alter Spalte in neue Spalten und das Entfernen alter / veralteter Spalten

Das Problem:

Betrachten wir zwei Anwendungsfälle:

  1. Ein Benutzer hat Version 1.0.0 heruntergeladen, das Update auf Version 1.1.0 übersprungen und entschieden, das Plugin zu aktualisieren, als die Version 2.0.0 veröffentlicht wurde. Wie organisiert man den database-Upgrade-process, der das Upgrade von Version 1.0.0 auf Version 2.0.0 einschließlich Änderungen von Version 1.1.0 behandelt?
  2. Ein Benutzer hat Version 2.0.0 heruntergeladen und auf einer leeren WordPress-Instanz installiert. Wie führt man die neueste Version der databaseinstallation durch, die alle Änderungen von allen Versionen enthält, die den DRY-Prinzipien entsprechen?

Solutions Collecting From Web of "Was ist der einfachste Weg, um kaskadierende database-Upgrades für mein Plugin zu implementieren?"

Um diese Probleme zu lösen, implementieren wir den kaskadierenden Upgrade-process, der beide Anwendungsfälle behandelt.

Als erstes können wir unseren Plugin-Aktivierungs-Haken implementieren, der unser Einstiegspunkt sein wird:

// define current plugin version define( 'WPSE8170_PLUGIN_VERSION', '2.0.0' ); // define our database table name define( 'WPSE8170_DB_TABLE', $GLOBALS['wpdb']->prefix . 'wpse8170_test_table' ); add_action( 'init', 'wpse8170_plugin_upgrade' ); // check database on init action, to be confident that our plugin database is up-to-date register_activation_hook ( __FILE__, 'wpse8170_plugin_upgrade' ); function wpse8170_plugin_upgrade() { $filter = 'wpse8170_upgrade_db'; $option = 'wpse8170_db_version'; // get current database version $db_version = get_option( $option ); // if database version is not exists, lets create new and set it to '0.0.0' if ( $db_version === false ) { $db_version = '0.0.0'; add_option( $option, $db_version, '', 'yes' ); } // check database version, if it equals to current plugin version, then no upgrades are required if ( version_compare( $db_version, WPSE8170_PLUGIN_VERSION, '=' ) ) { return; } // define our upgrade hooks, which will be called to upgrade database to a certain version add_filter( $filter, 'wpse8170_upgrade_to_10000' ); // upgrade db to version 1.0 add_filter( $filter, 'wpse8170_upgrade_to_11000' ); // upgrade db to version 1.1 add_filter( $filter, 'wpse8170_upgrade_to_20000' ); // upgrade db to version 2.0 // apply our upgrade filter and update database version update_option( $option, apply_filters( $filter, $db_version ) ); } 

Bevor Sie mit Upgrade-Hooks beginnen, können Sie eine Hilfsfunktion erstellen, mit deren Hilfe wir eine Reihe von SQL-Abfragen ausführen können:

 function wpse8179_execute_upgrade_queries( array $queries ) { global $wpdb; foreach ( $queries as $query ) { $wpdb->query( $query ); } } 

Sehen wir uns schließlich unsere Upgrade-Hooks an. database von 0.0.0 auf 1.0.0 aktualisieren:

 function wpse8170_upgrade_to_10000( $current_version ) { // define version of current upgrade hook $this_version = '1.0.0'; // if the version of current upgrade hook is less or equals to current database version, return it without any changes if ( version_compare( $current_version, $this_version, '>=' ) ) { return $current_version; } // execute all required queries to make database corresponding to current upgrade version wpse8179_execute_upgrade_queries( array( sprintf( "CREATE TABLE IF NOT EXISTS `%s` (`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `type` VARCHAR(15) NOT NULL, `data` TEXT NOT NULL, PRIMARY KEY (`id`) ) ENGINE = MyISAM", WPSE8170_DB_TABLE ), // above queries could be merged into one, but added as an example sprintf( "ALTER TABLE `%s` CHARACTER SET = utf8, COLLATE = utf8_general_ci;", WPSE8170_DB_TABLE ), sprintf( "ALTER TABLE `%s` CHANGE COLUMN `data` `data` TEXT CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' NOT NULL;", WPSE8170_DB_TABLE ), sprintf( "ALTER TABLE `%s` ADD INDEX `gchart_idx_type` (`type` ASC)", WPSE8170_DB_TABLE ), ) ); // return current upgrade version, which is equals to 1.0.0 return $this_version; } 

database von 1.0.0 auf 1.1.0 aktualisieren:

 function wpse8170_upgrade_to_11000( $current_version ) { // define version of current upgrade hook $this_version = '1.1.0'; // if the version of current upgrade hook is less or equals to current database version, return it without any changes if ( version_compare( $current_version, $this_version, '>=' ) ) { return $current_version; } // execute all required queries to make database corresponding to current upgrade version wpse8179_execute_upgrade_queries( array( // update table column type sprintf( "ALTER TABLE `%s` CHANGE COLUMN `data` `data` MEDIUMTEXT NOT NULL", WPSE8170_DB_TABLE ), // update table data sprintf( "UPDATE `%s` SET ... WHERE ...", WPSE8170_DB_TABLE ), ) ); // return current upgrade version, which is equals to 1.1.0 return $this_version; } 

database von 1.1.0 auf 2.0.0 aktualisieren:

 function wpse8170_upgrade_to_20000( $current_version ) { // define version of current upgrade hook $this_version = '2.0.0'; // if the version of current upgrade hook is less or equals to current database version, return it without any changes if ( version_compare( $current_version, $this_version, '>=' ) ) { return $current_version; } // execute all required queries to make database corresponding to current upgrade version wpse8179_execute_upgrade_queries( array( // update table by adding two new columns sprintf( "ALTER TABLE `%s` ...", WPSE8170_DB_TABLE ), // update table data by splitting data from old column into two new sprintf( "UPDATE `%s` SET ... WHERE ...", WPSE8170_DB_TABLE ), // delete deprecated column from the table sprintf( "ALTER TABLE `%s` ...", WPSE8170_DB_TABLE ), ) ); // return current upgrade version, which is equals to 2.0.0 return $this_version; } 

Sehen wir uns an, wie unser Ansatz beide Anwendungsfälle behandelt:

  1. Nach dem Upgrade von Version 1.0.0 auf Version 2.0.0 werden wir den Hook wpse8170_upgrade_to_10000 überspringen, da wir bereits die databaseversion 1.0.0 und die Hooks wpse8170_upgrade_to_11000 und wpse8170_upgrade_to_20000 , um unsere database auf die neueste Version einschließlich der verpassten Version 1.1.0 zu wpse8170_upgrade_to_20000
  2. Nach der Installation der neuesten Version des Plugins auf einer leeren WP-Instanz übergeben wir alle Upgrade-Hooks und erstellen unsere databasetabelle mit allen Änderungen, die in den Versionen 1.0.0 und 1.1.0 enthalten sind