WordPress save_post钩子致内容重复,需实现首次发布仅修改一次
WordPress文章内容重复问题修复方案
问题根源
你的代码出现内容重复,核心原因是:
save_post钩子会在wp_update_post执行时再次触发,即便临时移除钩子,仍存在重复执行的逻辑漏洞;- 用
get_post()获取的是数据库中已存储的内容,而非用户提交的原始内容,二次处理时容易导致内容叠加; - 强制设置
post_status = 'publish'会干扰WordPress默认发布流程,触发额外的钩子回调。
优化方案(推荐用wp_insert_post_data过滤器)
之前用这个过滤器崩溃大概率是写法错误,它是在内容存入数据库前修改数据,不会触发二次更新,更适配你的需求:
add_filter('wp_insert_post_data', 'my_modify_post_data', 10, 2); function my_modify_post_data($data, $postarr) { // 只处理文章类型,排除修订版、自动草稿 if ($data['post_type'] !== 'post' || $data['post_status'] === 'auto-draft' || isset($postarr['ID']) && wp_is_post_revision($postarr['ID'])) { return $data; } // 判断是否为首次发布:新增文章 或 从未发布过的文章转为发布状态 $is_first_publish = empty($postarr['ID']) || (get_post_status($postarr['ID']) !== 'publish' && $data['post_status'] === 'publish'); // 检查是否已经处理过,避免重复操作 if ($is_first_publish && !get_post_meta($postarr['ID'] ?? 0, 'check_post_style', true)) { $myweb_settings = get_option('your_settings_option_name'); // 替换为你的设置选项名 $add_extra_tag = $myweb_settings['myoption_set'] ?? ''; $post_checked = get_post_meta($postarr['ID'] ?? 0, 'my_post_meta_style', true); // 符合条件则处理内容 if (($add_extra_tag === 'Yes') || $post_checked) { $data['post_content'] = add_simple_tags($data['post_content']); $data['post_title'] = add_simple_tags($data['post_title']); // 标记为已处理(新增文章需在保存后添加meta) if (!empty($postarr['ID'])) { update_post_meta($postarr['ID'], 'check_post_style', '1'); } else { add_action('save_post', function($post_id) { update_post_meta($post_id, 'check_post_style', '1'); }, 20); } } } return $data; }
若坚持使用save_post钩子,修复后的代码
add_action('save_post', 'my_modified_content'); function my_modified_content($post_id) { // 排除修订版、自动草稿、非文章类型 if (wp_is_post_revision($post_id) || get_post_status($post_id) === 'auto-draft' || get_post_type($post_id) !== 'post') { return; } // 验证请求合法性 if (!check_admin_referer('update-post_' . $post_id, '_wpnonce')) { return; } // 检查是否已处理过 $alreadydone = get_post_meta($post_id, 'check_post_style', true); if ($alreadydone === '1') { return; } // 判断是否为首次发布:发布时间与修改时间一致 $is_first_publish = get_post_status($post_id) === 'publish' && get_post_field('post_date_gmt', $post_id) === get_post_field('post_modified_gmt', $post_id); if (!$is_first_publish) { return; } $myweb_settings = get_option('your_settings_option_name'); // 替换为你的设置选项名 $add_extra_tag = $myweb_settings['myoption_set'] ?? ''; $post_checked = get_post_meta($post_id, 'my_post_meta_style', true); if (($add_extra_tag === 'Yes') || $post_checked) { // 临时移除钩子,避免wp_update_post触发重复执行 remove_action('save_post', 'my_modified_content'); // 获取用户提交的原始内容,而非数据库中的内容 $content = add_simple_tags($_POST['post_content'] ?? get_post_field('post_content', $post_id)); $title = add_simple_tags($_POST['post_title'] ?? get_post_field('post_title', $post_id)); // 更新文章,不强制设置post_status,保留原有状态 wp_update_post([ 'ID' => $post_id, 'post_title' => $title, 'post_content' => $content ]); // 标记为已处理 update_post_meta($post_id, 'check_post_style', '1'); // 重新添加钩子 add_action('save_post', 'my_modified_content'); } }
关键修复点
- 排除修订版和自动草稿,避免不必要的回调;
- 验证请求合法性,防止恶意触发;
- 精准判断首次发布场景,确保仅处理一次;
- 使用用户提交的原始内容(
$_POST)而非数据库内容,避免重复处理; - 移除不必要的
post_status强制设置,遵循WordPress默认流程。
内容的提问来源于stack exchange,提问作者OneNation
相关产品推荐
相关产品推荐

