WordPress save_post钩子更新元数据未触发逻辑修复方案
问题原因
你写的自定义逻辑目前只绑定了WordPress文章主表(wp_posts)保存相关的钩子(比如save_post、post_updated)。当你仅更新文章元数据时,WordPress不会走文章主表的保存流程,只会单独写入元数据表(wp_postmeta),所以你的函数根本不会被触发,自然拿不到最新的元数据值。
另外你现有代码还有两个影响功能的问题:
- 直接拦截所有REST_REQUEST请求的逻辑,会导致古腾堡编辑器、第三方接口通过REST路径更新内容/元数据时,逻辑完全不生效
- 读取元数据时直接取数组下标
[0],如果对应元数据不存在,会触发PHP数组偏移错误
修复方案
- 把核心的PDF生成逻辑抽成独立公共函数,供不同触发场景复用,避免重复写冗余代码
- 保留原有文章保存时的触发逻辑,额外挂载
updated_post_meta钩子,覆盖单独更新元数据的场景 - 增加重复执行拦截标记,避免同时触发文章保存、元数据更新钩子时,Python脚本被重复执行
- 优化原有的请求拦截逻辑,给元数据读取加空值兜底,修复现有报错隐患
修复后完整代码
// 核心PDF生成逻辑,抽为公共函数 function trigger_pdf_generation($post_id) { // 静态标记,防止同一次请求内重复执行脚本 static $executed = false; if ($executed) { return; } // 基础校验 $post = get_post($post_id); if (!$post || $post->post_type !== 'item') { return; } if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) { return; } if (in_array($post->post_status, ['trash', 'draft', 'auto-draft'])) { return; } // 移除一刀切的REST请求拦截,改为权限校验,避免REST路径更新时逻辑失效 if (!current_user_can('edit_post', $post_id)) { return; } // 读取元数据时直接取单值,增加空值兜底,避免数组偏移报错 $dig = get_post_meta($post_id, 'wpcf-digitisation-project-no', true); $inv = get_post_meta($post_id, 'wpcf-inventory-no', true); if (empty($inv)) { return; } // 拼接执行命令 if (!empty($dig)) { $command = escapeshellcmd('python3 ' . dirname(__FILE__) . '/create_pdf.py digital ' . $inv); } else { $command = escapeshellcmd('python3 ' . dirname(__FILE__) . '/create_pdf.py hmml ' . $inv); } exec($command, $output, $ret_code); $log_file = dirname(__FILE__) . '/my_logs.txt'; $fp = fopen($log_file, 'a+'); if ($ret_code !== 0) { fwrite($fp, "\nFailed to create pdf for record with inventory number: " . $inv . "\n"); } else { fwrite($fp, "\nPDF successfully created for record with inventory number: " . $inv . "\n"); } fclose($fp); $executed = true; } // 原有触发逻辑:文章保存时执行 add_action('save_post', 'trigger_pdf_generation', 20, 1); // 新增触发逻辑:依赖的元数据更新时执行 add_action('updated_post_meta', function($meta_id, $post_id, $meta_key, $meta_value) { // 仅监听业务依赖的两个字段变更,无关元数据更新时不触发逻辑 $target_meta_keys = ['wpcf-digitisation-project-no', 'wpcf-inventory-no']; if (in_array($meta_key, $target_meta_keys)) { trigger_pdf_generation($post_id); } }, 20, 4);
注意事项
- 元数据更新的钩子加了字段过滤,只有你业务用到的两个元数据变更时才会触发脚本,避免其他无关元数据更新时做无用功
get_post_meta第三个参数传true会直接返回单条元数据值,比取全量数组再拿下标更稳定,自带空值兜底- 静态变量
$executed会标记当前请求内脚本是否已经执行过,哪怕一次操作同时触发多个钩子,也只会生成一次PDF,不会重复执行
内容的提问来源于stack exchange,提问作者Martha
相关产品推荐
相关产品推荐

