WordPress Autosave Rest API Hook

WARNING: This article may be obsolete
This post was published in 2022-01-21. Obviously, expired content is less useful to users if it has already pasted its expiration date.

注意
请再次确认本文标题,确认这是你需要的内容,因为绝大部分人都想要取消WordPress的自动保存功能,但本文的内容恰好完全相反:不仅不会删除revisions,还会试图拿下每一次“自动保存”的数据

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文件过大的问题。


 Last Modified in 2022-02-26 


Leave a Comment Anonymous comment is allowed / 允许匿名评论