This post was published in 2022-01-21. Obviously, expired content is less useful to users if it has already pasted its expiration date.
Table of Contents
Autosave的机制
Interval
在 config.php 配置文件里,自动保存的间隔是可以修改的:
// 每120秒自动保存一次
define('AUTOSAVE_INTERVAL', 120 );
wp_posts写入机制
古腾堡编辑器有两种保存机制: save (保存)和 autosave (自动保存)。 前者是手动触发的(比如按了保存按键,或者发表一篇文章),后者是自动触发的,比如按照上面的 config.php 配置文件,120秒就会自动保存一次。
每当Wordpress执行一次 save , wp_posts 表就会给当前的文章保存一份完整的副本(新增一行),作为 revision ;每当Wordpress执行一次 autosave , wp_posts 表并不会新增一行数据,而是会 更新 一行被标记为"autosave"的数据。
所以,从数据库表的角度来看:如果你是一个Ctrl+S爱好者,你的wp_posts表会挤满了很多很多文章的 revision 数据。大多数Wordpress数据库优化插件都会拿这个作为优化的第一步,清理这些revisions,让wp_posts表体积减小。Autosave的机制则完全不同:Autosave仅仅会不断的覆盖相同的一行数据,而不像手动save那样每次都保存一个完整、独立的文章副本。
自动保存每一份Autosave
所以就有了这样一段代码:它能过滤每一次Autosave动作,并筛选出每一次Autosave的数据:
<?php
add_filter('rest_post_dispatch', 'listen_autosave_api', 10, 3);
function listen_autosave_api($result, $server, $request)
{
if (is_array($result->data)) {
if (isset($result->data['guid']['raw']) && isset($result->data['modified_gmt']) && isset($result->data['content']['raw'])) {
$post_guid = $result->data['guid']['raw'];
$post_title = $result->data['title']['raw'];
$post_modified_gmt = $result->data['modified_gmt'];
$post_content = $result->data['content']['raw'];
if (isset($result->data['parent'])) {
if ($result->data['parent'] != 0) {
$post_parent_id = $result->data['parent'];
} else {
$post_parent_id = $result->data['id'];
}
} else {
$post_parent_id = $result->data['id'];
}
// do whatever you want, e.g. save the data
}
}
return $result;
}
修改代码的第22行,接下来你就可以对这些数据进行任何你想要的操作了。你可以塞入自己新建的表里,也可以塞mongoDB里,还可以塞git仓库里作为一次commit,但无论如何都不建议塞进wp_posts里。当然你也可以修改代码的第7~10行,获取rest api更多的数据。同时不要忘了修改 define('AUTOSAVE_INTERVAL', 120 ); ,也许你想让它大一些,也许想让它小一些。
数据库表体积爆炸的遗留问题
可能也有人会遇到数据库表体积爆炸增大的问题,这个问题可以用InnoDB Page Compression来解决(如果不喜欢全局压缩,也可以使用 PAGE_COMPRESSED = 1 指定某些表进行压缩)。备份数据库(mysqldump)的时候可以用Linux pipe + gzip,或者Linux pipe + zstd,这样就可以避免遇到.sql文件过大的问题。