WordPress自定义文章类型变更调用函数,ACF字段为空问题求助
解决ACF字段在
transition_post_status钩子中获取为null的问题 你猜的完全没错!transition_post_status的触发时机确实早于ACF将字段值写入数据库的时间——尤其是在首次发布新文章的时候:WordPress会先完成文章状态的转换(把文章设为publish),之后ACF才会把你填写的自定义字段值保存到数据库里。这就是为什么新发布时ACF字段返回null,而更新文章时能正常获取的原因(更新时字段已存在于数据库,即使钩子触发时机稍早,也能读到有效值)。
要解决这个问题,最靠谱的方式是改用ACF专门提供的钩子处理发布/更新场景,同时单独处理删除操作,具体方案如下:
具体实现代码
我们把生成JSON的逻辑抽成独立函数,方便在不同钩子中复用:
// 监听ACF字段保存完成,处理文章发布/更新 add_action('acf/save_post', 'handle_resources_save_or_update', 20); function handle_resources_save_or_update($post_id) { $post = get_post($post_id); // 只针对「resources」自定义文章类型 if ($post->post_type !== 'resources') { return; } // 只处理已发布的文章(如果需要忽略草稿、待审等状态可保留此判断) if ($post->post_status !== 'publish') { return; } // 调用生成JSON的通用函数 generate_resources_json(); } // 监听文章删除事件 add_action('delete_post', 'handle_resources_delete'); function handle_resources_delete($post_id) { $post = get_post($post_id); if ($post->post_type !== 'resources') { return; } // 删除后重新生成JSON generate_resources_json(); } // 统一的JSON生成逻辑,复用性更强 function generate_resources_json() { $args = array( 'post_type' => 'resources', 'post_status' => 'publish', 'posts_per_page' => -1 ); $queryResults = new WP_Query($args); $resources_data = array(); if ($queryResults->have_posts()) { while ($queryResults->have_posts()) { $queryResults->the_post(); // 现在可以正常获取所有ACF字段了 $resource_item = array( 'id' => get_the_ID(), 'title' => get_the_title(), 'publish_date' => get_the_date('Y-m-d H:i:s'), // 替换成你的实际ACF字段名 'resource_category' => get_field('resource_category'), 'download_link' => get_field('download_link'), 'resource_description' => get_field('resource_description') ); $resources_data[] = $resource_item; } wp_reset_postdata(); // 必须重置查询,避免影响后续全局变量 } // 生成JSON文件(示例保存到主题目录的exports文件夹) $json_content = json_encode($resources_data, JSON_PRETTY_PRINT); $export_dir = get_stylesheet_directory() . '/exports'; $export_file = $export_dir . '/resources.json'; // 确保目录存在,不存在则创建 if (!file_exists($export_dir)) { wp_mkdir_p($export_dir); } // 写入文件 file_put_contents($export_file, $json_content); }
关键细节说明
acf/save_post钩子的优先级:我们设置为20,因为ACF默认的字段保存逻辑是在优先级10执行的,晚一点触发能确保字段已经完全写入数据库。- 删除操作的处理:删除文章不会触发
acf/save_post,所以单独用delete_post钩子监听,删除后重新生成JSON即可自动排除已删除的内容。 - 查询重置:
wp_reset_postdata()必须调用,否则后续WordPress函数可能会使用错误的全局$post变量,引发奇怪的问题。
内容的提问来源于stack exchange,提问作者Tasos
相关产品推荐
相关产品推荐

