
在 woocommerce 中,使用 `save_post_product` 钩子时直接调用 `$post->get_type()` 无法可靠获取产品类型(如 grouped、variable),因其依赖未完全初始化的 post 对象;应改用 `woocommerce_after_product_object_save` 钩子配合 `wc_get_product()` 获取完整产品实例。
WooCommerce 的产品类型(如 simple、grouped、variable、external)由其底层 WC_Product 子类决定,而原生 WordPress 的 save_post_product 钩子触发时,$post 仅是 WP_Post 对象,不包含 WooCommerce 产品元数据和类型逻辑。因此 $post->get_type() 实际调用的是 WP_Post::get_type()(返回 'product'),或在某些上下文中因对象未正确转换而错误返回 'simple' —— 这正是你遇到的问题:新建分组商品时返回 simple,更新后才显示 grouped。
✅ 正确做法是使用 WooCommerce 提供的专用钩子:
woocommerce_after_product_object_save —— 该钩子在产品对象(WC_Product 实例)完成持久化后触发,并传入已加载全部属性的 $product 对象,确保 get_type()、is_type()、get_children() 等方法可安全调用。
以下是推荐实现(已修正原答案中的变量引用错误):
add_action('woocommerce_after_product_object_save', 'nd_update_group_product_attributes_func', 10, 2);
function nd_update_group_product_attributes_func($product, $data_store) {
// ✅ 安全获取真实产品类型
$product_type = $product->get_type(); // 如 'grouped', 'variable', 'simple'
// 仅对分组产品执行逻辑
if ($product->is_type('grouped')) {
$child_ids = $product->get_children(); // 返回整型 ID 数组
$all_bedroom_terms = array();
foreach ($child_ids as $child_id) {
$child_product = wc_get_product($child_id);
if (!$child_product) continue;
// 获取子商品的 'pa_bedrooms' 属性值(注意:返回字符串,非数组)
$bedroom_value = $child_product->get_attribute('pa_bedrooms');
if (!empty($bedroom_value)) {
$all_bedroom_terms[] = $bedroom_value;
}
}
// 去重并同步到当前分组产品(作为分类法 term 关联)
$unique_terms = array_unique($all_bedroom_terms);
if (!empty($unique_terms)) {
// ⚠️ 注意:$product 是 WC_Product 对象,无 $post_ID;需用 $product->get_id()
wp_set_object_terms($product->get_id(), $unique_terms, 'pa_bedrooms', false);
}
}
}? 关键注意事项:
- 不要在 woocommerce_after_product_object_save 中使用 $post_ID 或 $post:该钩子不传递 WordPress 原生 post 参数,$product->get_id() 是唯一可靠 ID 来源;
- get_attribute('pa_bedrooms') 返回单个字符串(非数组),若需多值请检查属性是否为多选或使用 get_terms() 查询;
- wp_set_object_terms(..., false) 表示替换而非追加,避免重复累积旧值;
- 若需兼容自定义产品类型,可用 $product->is_type(['grouped', 'bundle']) 多类型判断。
此方案确保类型识别 100% 准确,且与 WooCommerce 数据生命周期严格对齐,是官方推荐的最佳实践。










