好的,为了解决这些问题,让我们实现级联升级过程,它将处理这两个用例。
首先,让我们实现插件激活挂钩,这将是我们的切入点:
// 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 ) );
}
在开始研究升级挂钩之前,让我们创建一个助手函数,它将帮助我们执行一组sql查询:
function wpse8179_execute_upgrade_queries( array $queries ) {
global $wpdb;
foreach ( $queries as $query ) {
$wpdb->query( $query );
}
}
最后,让我们看看我们的升级挂钩。将数据库从0.0.0升级到1.0.0:
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;
}
将数据库从1.0.0升级到1.1.0:
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;
}
将数据库从1.1.0升级到2.0.0:
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;
}
让我们看看我们的方法如何处理这两个用例:
从1.0.0版升级到2.0.0版后,我们将跳过挂钩wpse8170_upgrade_to_10000
因为我们已经有数据库版本等于1.0.0
并穿过挂钩wpse8170_upgrade_to_11000
和wpse8170_upgrade_to_20000
将数据库升级到最新版本,包括缺失的1.1.0版本在空白WP实例上安装最新版本的插件后,我们将通过所有升级挂钩,并使用版本1.0.0和1.1.0中包含的所有更改构建数据库表