一些WordPress插件(尽管很少)使用数据库中的post_content_filtered列来保存与帖子有关的一些数据。例如,保存时的Markdown在Mark4312079q列中分别存储帖子的markdown版本和post_content_formatted列中的已解析HTML,因此当停用插件时,帖子不会喷出Markdown(因为HTML存储在post_content中)。

现在,我开始意识到post_content很漂亮大量用于临时存储,即在以下情况下,列中的内容会丢失(或清除):


,您使用'更改帖子(标题,标签,类别等)快速编辑”选项
(自动)发布计划的帖子
您对帖子进行批量编辑
您在帖子的修订之间切换
帖子是从外部编辑器保存的(即不是WordPress帖子编辑器)

问题:


在其他情况下,post_content_filtered列中的数据是否被清除?
有办法吗?上一个难道这根本没有发生? (我的意思是,有没有一种方法可以确保数据被永久存储,即post_content_filtered列的处理方式?)


#1 楼

WordPress中的每个帖子更新均由wp_update_post函数处理。

此函数具有一些默认值,而对于post_content_filtered,默认值是''(空字符串)。

默认值与通过wp_parse_args传递给函数的args合并,这意味着每次更新帖子且未显式传递post_content_filtered时,它都设置为空字符串。

现在我们可以问:什么时候post_content_filtered已明确传递给wp_update_post?答案是:永远不要使用WordPress。

那么对于您的第一个问题:


在其他什么情况下,post_content_filtered
列中的数据也会被清除?


简单的回答是:每次更新帖子,出于任何原因。
请注意,仅更改一个字段即是更新,尤其是每个状态变化是一个更新,例如要发布的草稿,待发布的出版物,将来要发布的文章,将其发布到垃圾箱(帖子删除),依此类推...

如果帖子中发生更改,则post_content_filtered被清除;唯一的例外是当post_content_filtered显式传递给wp_update_post时,并且正如已经说过的那样,WordPress永远不会做到这一点。


有什么办法可以防止这种情况的发生? (我的意思是,
是否有办法确保数据被永久存储?


如果您使用代码创建该字段,并且想要保留它,您必须查看WordPress执行的每个更新,并防止更改。

这听起来像是艰苦的工作,但是如果您阅读此答案的第一句话,“ WordPress中的每个更新都会处理通过wp_update_post函数”,您了解到,唯一需要看的就是该函数,幸运的是它具有不同的钩子。

我建议使用的钩子是wp_insert_post_data,其原因有两个:


它在更新之前运行,因此您不必恢复,但是您可以
防止它

它传递2个参数:函数要访问的数据更新,并
传递的参数数组(在更新的情况下)包含帖子的ID。

因此,使用简单的get_post,您就可以比较帖子现在的状态以及帖子的状态:如果您不喜欢某些东西,则可以对其进行更改。

我们的代码:

add_filter( 'wp_insert_post_data', 'preserve_content_filtered', 999, 2 );

function preserve_content_filtered ( $data, $postarr ) {

    /* If this is not an update, we have nothing to do */
    if ( ! isset($postarr['ID']) || ! $postarr['ID'] ) return $data;

    /*
     * Do you want you filter per post_type?
     * You should, to prevent issues on post type like menu items.
     */
    if ( ! in_array( $data['post_type'], array( 'post', 'page' ) ) ) return $data;

    /* How post is now, before the update */
    $before = get_post( $postarr['ID'] ); 

    /* If content_filtered is already empty we have nothing to preserve */
    if ( empty( $before->post_content_filtered ) ) return $data;

    if ( empty( $data['post_content_filtered'] ) ) {
        /*
         * Hey! WordPress wants to clear our valuable post_content_filtered...
         * Let's prevent it!
         */
        $data['post_content_filtered'] = $before->post_content_filtered;
    }

    return $data;

}


存在一个可能的问题,其中前一个该功能可防止每次清洁post_content_filtered。如果出于任何原因要清除它?

我说过,每个WP帖子的更改都由wp_update_post处理,但您不是WordPress。

您可以编写如下函数:

function reset_post_content_filtered( $postid ) {
    global $wpdb;
    $wpdb->query( $wpdb->prepare(
        "UPDATE $wpdb->posts SET `post_content_filtered` = '' WHERE `ID` = %d", $postid
    ) );
}


作为$wpdb查询,它不会触发我们的过滤器,因此重置可以毫无问题地完成,并且在您的代码中的任何地方都可以需要重置post_content_filtered,您可以调用此函数。

还可以创建带有“清除内容过滤”按钮的metabox,单击此按钮后只需调用reset_post_content_filtered函数,例如通过Ajax。