使用Wordpress,尤其从3.0走入Wordpress世界的朋友,也许都遇到过一个问题:自动保存(Auto-Save)和文章修订(Post-Revisioning)功能导致文章ID不连续的问题。有时还特别夸张。
去掉自动草稿的功能
造成发布文章ID不连续的原因有三:
自动保存功能 Auto-Save;
历史版本 Post Revisions;
自动草稿功能 Auto-Draft!
针对WordPress 3.9.x,这里给大家介绍一个解决ID不连续发方法:
打开%WP%/wp-config.php文件,在 “$table_prefix = ‘wp_’;” 前面添加如下代码(注意,一定是”$table_prefix = ‘wp_’;”这行的前面):
define('WP_POST_REVISIONS', false); define('AUTOSAVE_INTERVAL', false);
找到并打开%WP%/wp-admin/post-new.php ,将其 “wp_enqueue_script(‘autosave’);” 注释或删除掉。如下:
//wp_enqueue_script('autosave');
找到 %WP%/wp-admin/post.php 文件中要将
//if ( 'attachment' !== $post_type ) //wp_enqueue_script('autosave');
经过上面的修改后,文章的自动保存和历史版本都关闭了。不过,这里也带来了一个副作用:预览不能使用了,需要手动保存草稿后才行。美中不足吧。
另外,还有个自动草稿功能,我们下面会介绍如何处理。
删除无用的草稿
在“删除草稿”方面,有一些相应的插件,比如Delete-Revision,但是给Wordpress安装过多的插件会降低她的速度。
注意,请在进行如下工作前,备份数据库!防止把数据搞坏。
我们先来看一下冗余数据(无用的自动修订、草稿等)。登陆phpMyAdmin(一般虚拟主机都会提供的),然后选中相应的数据库,然后在里面执行如下SQL:
-- 查看自动修订产生的冗余数据 -- 注意,请根据自己的情况,修改表名(主要是表前缀) SELECT * FROM `wp_posts` WHERE `post_type` = 'revision';
这里显示内容都是一些冗余的数据,可以直接删除。删除SQL如下:
-- 删除冗余数据 DELETE FROM `wp_posts` WHERE `post_type` = 'revision';
重用自动草稿产生的ID
使用关闭WordPress的自动保存后,虽然页面上不提示自动保存了,但是在数据库中还会看到自动保存的自动草稿.现在找一个完美版的关闭自动保存.
找到”/wp-admin/includes/post.php”文件,搜索”$create_in_db”,不含引号。可以发现,以下的代码就是产生这个自动草稿的:
if ( $create_in_db ) { $post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) ); $post = get_post( $post_id ); if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) && get_option( 'default_post_format' ) ) set_post_format( $post, get_option( 'default_post_format' ) ); } else { $post = new stdClass; $post->ID = 0; $post->post_author = ''; $post->post_date = ''; $post->post_date_gmt = ''; $post->post_password = ''; $post->post_type = $post_type; $post->post_status = 'draft'; $post->to_ping = ''; $post->pinged = ''; $post->comment_status = get_option( 'default_comment_status' ); $post->ping_status = get_option( 'default_ping_status' ); $post->post_pingback = get_option( 'default_pingback_flag' ); $post->post_category = get_option( 'default_category' ); $post->page_template = 'default'; $post->post_parent = 0; $post->menu_order = 0; $post = new WP_Post( $post ); }
修改业务逻辑,将上述代码用下面代码替代即可
//替换后,可以重用自动草稿 if ( $create_in_db ) { global $current_user;//获取当前登录用户 //获取最早一条自动草稿 //升级到4.01后获取不到$wpdb,需要增加以下代码 global $wpdb; $post = $wpdb->get_row( "SELECT * FROM $wpdb->posts WHERE post_status = 'auto-draft' AND post_type = '$post_type' AND post_author = $current_user->ID ORDER BY ID ASC LIMIT 1" ); if ( !$post ) { //没有记录添加一条草稿记录 $post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) ); $post = get_post( $post_id ); } if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) && get_option( 'default_post_format' ) ) set_post_format( $post, get_option( 'default_post_format' ) ); }
修改完毕后上传空间覆盖你的源文件即可!当然,你还需要一个插件,叫做Super Switch,请安装后,将“保存修订版本”和“自动保存”设为禁止,这样才能完美的关闭WordPress的自动草稿功能!
生成添加“草稿”的数据(利用空余的id)
经过上面的折腾,空出来一些ID。既然自动草稿的记录能使用,那么空出来的ID更加可以随意使用。现在,我们就想办法把这些空出来的ID也使用起来。
根据网友测试结果显示,经过修改上面的代码修改后,只要手动保持wp_posts表中数据的三个字段内容如下,那么这些空出来的ID也可以被使用起来。
post_status='auto-draft' guid='http://youdomain/?p={$ID}' post_type='post' // ID不能为空,还有和{$ID}保持一致; ID // post_author字段也要填上相应作者的ID。 post_author
将空出来的ID分别安装上面的要求,将对应一列数据造出来即可。我们上面提到,Wordpress会自动添加自动草稿的记录,并且七天后就自动删除。那么,我们要在两个时间相关的字段post_date和post_modified上,填上一个尽可能打一点的值,防止Wordpress自动删除。但是,系统还有可能产生自动草稿。那么,为了防止被删除,系统产生的这些自动草稿记录要优先使用掉。所以,我们上面的SQL中,有按照时间排序的条件。
既然有了上面这些要求,那么我们就写一个SQL语句,来自动生成数据。SQL如下:
-- 生成n以内的空ID对应的记录 CREATE TABLE post_bk as SELECT iid AS ID, 'auto-draft' as post_status, CONCAT('https://www.5ycode.com/?p=', iid) AS guid, 'post' AS post_type, 1 as post_author, str_to_date('11.25.2015 00:00:00', '%m.%d.%Y %H:%i:%s') as post_date, str_to_date('12.26.2015 21:44:00', '%m.%d.%Y %H:%i:%s') as post_modified from ( select b.dd * 50 + a.dd as iid --生成的id数=n*9+9 from ( select 1 as dd union all select 2 union all select 3 union all select 4 union all select 0 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) a, (select 0 as dd union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) b ) num WHERE iid > 0 and iid NOT IN ( SELECT ID from wp_posts ) ORDER BY iid ASC;
将备份表中生成的数据导入到post里
insert into `wp_posts` (`ID`, `post_status`, `guid`, `post_type`, `post_author`, `post_date`, `post_modified`) select `post_bk`.`ID`, `post_bk`.`post_status`, `post_bk`.`guid`, `post_bk`.`post_type`, `post_bk`.`post_author`, `post_bk`.`post_date`, `post_bk`.`post_modified` from `post_bk`
参考文章:http://www.diguage.com/archives/5.html
文章评论
你写的这个和源地址写的不一样呀。
@匿名 这个是几种方式的整合,加上自己的的理解,比其他人的要全吧
@yxkong 关键我是小白,不知道删掉
} else {
$post = new stdClass;
这里一大段会有什么影响??还忘博主告知。
@匿名 不会有影响,加上也行。php是弱语言,$post对象为null
$post->post_content = apply_filters( 'default_content', $post_content, $post );
到这句话的时候会给它创建一个新实例,所以else那句话要不要都行。java的话就必须了
@yxkong 谢谢指点。