数据库中的’post_content_filtered’ 列何时被 WordPress 清除?
问题描述
一些 WordPress 插件 (尽管很少) 使用数据库中的 post_content_filtered
列来保存一些与文章相关的数据。
例如,Markdown on Save 分别将 post_content_formatted
列中的解析后的 HTML 和 post_content
列中的 HTML 分开存储在一起,这样当插件被禁用时,这些帖子不会显示出 Markdown(因为 HTML 存储在 post_content
中) 。
现在,我意识到 post_content_filtered
几乎用于临时存储,即:列中的内容丢失 (或清除):
-
您使用’Quick Edit’ 选项更改帖子 (标题,标签,类别等)
-
(自动) 发布预定的帖子
-
您可以批量修改帖子
-
你在一个帖子的修订之间切换
-
一个帖子从外部编辑器 (即不是 WordPress 的帖子编辑器) 保存起来
问题:
-
在其他情况下,
post_content_filtered
列中的数据是否已清除? -
有办法防止这种情况发生吗? (我的意思是,有没有办法确保数据被永久存储,
post_content
列的处理方式?)
最佳解决方案
WordPress 中的每个帖子更新都由 wp_update_post
函数处理。
此功能有一些默认值,而对于 post_content_filtered
,默认值为”(空字符串) 。
一旦默认值与通过 wp_parse_args
传递给函数的 args 合并,这意味着每次更新一个帖子并且没有明确传递 post_content_filtered
时,它被设置为一个空字符串。
现在我们可以问:post_content_filtered
是什么时候显式传递给 wp_update_post
?答案是:永远不要用 WordPress 。
所以对于你的第一个问题:
In what other situations is the data in the post_content_filtered column cleared?
简短的回答是:每次更新一个帖子,都是因为任何原因。
请注意,仅更改一个字段是更新,特别是每个状态更改都是更新。草稿发布,等待发布,未来发布,发布到垃圾 (一个帖子删除) 等等…
如果帖子发生变化,则 post_content_filtered
被清除; 只有当 post_content_filtered
被明确传递给 wp_update_post
时才是异常,而且如上所述,这是从来没有由 WordPress 完成的。
Is there a way to prevent this from happening at all? (I mean, is there a way to make sure that the data is stored permanently?
如果您使用代码创建该字段,并且要保留它,则必须查看 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 。
参考文献
注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。