使用acf/save_post同步自定义文章类型分类项问题排查
问题概述
我有两个自定义文章类型:
- 产品独立设计(
designs),对应专属分类法:design-library-tags(标签)、ratings(评分) - WooCommerce的
product类型,已创建自定义分类法:ratings-products(产品评分)、product_tag(产品标签)
需求:在产品编辑页通过ACF关联字段关联designs后,保存时自动将designs的标签和评分同步到对应产品的分类法中。
调试情况:在子主题functions.php中编写了代码,通过Cookie调试发现,执行到wp_get_object_terms获取designs的ratings分类项时,后续的chris_vardump5 Cookie始终无法生成,无报错但无法遍历返回结果。因后台保存页面会刷新,无法使用echo/print_r输出调试,只能依赖Cookie排查,每次调试前会手动清除Cookie。
原代码:
//Custom ACF Save to set design themes/ratings when a relationship is established between a product and a design // save post action add_action('acf/save_post', 'set_design_themes_and_rating_on_save', 20); /** * @param $post_id int|string */ function set_design_themes_and_rating_on_save($post_id) { // get our current post object $post = get_post($post_id); $rating = ''; $design_themes = array(); //setcookie('chris_vardump1', 'stage 1 - '.serialize($post), time()+3600*24, '/', 'staging.burlybottomdesigns.com'); // if post is object if(is_object($post)) { //setcookie('chris_vardump2', 'stage 2 if post object', time()+3600*24, '/', 'staging.burlybottomdesigns.com'); // check we are on the projects custom type and post statuses are either publish or draft // change 'projects' post type to your post type name which has the relationship field if($post->post_type === 'product' && ($post->post_status === 'publish' || $post->post_status === 'draft')) { //setcookie('chris_vardump3', 'stage 3 post_type=product', time()+3600*24, '/', 'staging.burlybottomdesigns.com'); // get relationship field employees // this example uses Post Object as the Return Format and is a multiple value // change get field param 'employees' to your relationship field name $designs = get_field('design_name'); if($designs) { foreach($designs as $design) { setcookie('chris_vardump4', $design->ID, time()+3600*24, '/', 'staging.burlybottomdesigns.com'); $rating = wp_get_object_terms($design->ID, 'ratings'); if( empty($rating) ) setcookie('chris_vardump5', 'rating empty', time()+3600*24, '/', 'staging.burlybottomdesigns.com'); else if ( is_wp_error($rating) ) setcookie('chris_vardump5', $rating->get_error_message(), time()+3600*24, '/', 'staging.burlybottomdesigns.com'); else if( !empty($rating) && !is_wp_error($rating) ) setcookie('chris_vardump5', $rating->count, time()+3600*24, '/', 'staging.burlybottomdesigns.com'); else setcookie('chris_vardump5', 'total failure', time()+3600*24, '/', 'staging.burlybottomdesigns.com'); } } // remove the action remove_action('acf/save_post', 'acf_save_post'); //Set the rating and product tags from the design once we manage to //retrieve them //wp_set_object_terms($post_id, $new_rating, 'ratings-products', false); //wp_set_object_terms($post_id, $new_design_themes, 'product_tag', false); // re add the action add_action('acf/save_post', 'acf_save_post'); } } // finally return return; }
问题排查与修复方案
核心问题分析
- ACF字段返回值不兼容:代码默认
get_field('design_name')返回Post Object数组,但如果ACF关联字段的返回格式设置为Post ID,$design会是数字ID而非对象,调用$design->ID会直接触发致命错误,导致后续代码完全无法执行,这就是chris_vardump5无法生成的根本原因。 - Cookie覆盖问题:如果关联多个
designs,循环内的setcookie会覆盖之前的Cookie值,最终只能看到最后一个design的调试结果。 - 冗余的ACF动作操作:代码中
remove_action和add_action完全没必要,反而可能引发未知的动作执行异常。
修复后的代码
// 关联产品与设计后,同步设计的标签和评分到产品分类法 add_action('acf/save_post', 'sync_design_taxonomies_to_product', 20); /** * @param int|string $post_id */ function sync_design_taxonomies_to_product($post_id) { // 获取当前文章对象,非产品类型直接返回 $post = get_post($post_id); if (!is_object($post) || $post->post_type !== 'product') { return; } // 仅处理发布/草稿状态的产品 if (!in_array($post->post_status, ['publish', 'draft'])) { return; } // 获取ACF关联的设计,兼容Post Object和Post ID两种返回格式 $designs = get_field('design_name'); if (empty($designs)) { return; } // 统一转换为设计ID数组 $design_ids = []; foreach ($designs as $design) { $design_ids[] = is_object($design) ? $design->ID : (int)$design; } // 收集所有设计的标签和评分(用slug避免名称重复问题) $all_tags = []; $all_ratings = []; foreach ($design_ids as $design_id) { // 获取设计的评分分类slug $ratings = wp_get_object_terms($design_id, 'ratings', ['fields' => 'slugs']); if (!is_wp_error($ratings) && !empty($ratings)) { $all_ratings = array_merge($all_ratings, $ratings); } // 获取设计的标签分类slug $tags = wp_get_object_terms($design_id, 'design-library-tags', ['fields' => 'slugs']); if (!is_wp_error($tags) && !empty($tags)) { $all_tags = array_merge($all_tags, $tags); } } // 去重后同步到产品对应分类法(false表示追加,true表示替换) if (!empty($all_ratings)) { wp_set_object_terms($post_id, array_unique($all_ratings), 'ratings-products', false); } if (!empty($all_tags)) { wp_set_object_terms($post_id, array_unique($all_tags), 'product_tag', false); } }
调试优化建议
放弃Cookie调试,改用WordPress自带的error_log函数,不受页面刷新影响,调试信息更完整:
// 示例:替换Cookie的调试代码 error_log('当前处理的设计ID: ' . $design_id); $ratings = wp_get_object_terms($design_id, 'ratings'); error_log('获取到的评分分类: ' . print_r($ratings, true));
调试信息会输出到服务器的PHP错误日志中(具体路径可咨询主机商或查看php.ini配置)。
内容的提问来源于stack exchange,提问作者atwookie
相关产品推荐
相关产品推荐

