
本文介绍在 woocommerce 商品保存后可靠获取其真实产品类型的正确方法,解决 `save_post_product` 钩子中 `get_type()` 返回错误类型(如始终返回 `simple`)的问题,并推荐使用更可靠的 `woocommerce_after_product_object_save` 钩子及 `wc_get_product()` 实例化方式。
在 WooCommerce 开发中,常需在商品保存后根据其类型(如 grouped、variable、external 等)执行特定逻辑。但若直接在 save_post_product 钩子中调用 $post->get_type(),会遇到一个典型问题:该方法在钩子触发时尚未完成产品对象的完整初始化,导致 get_type() 常常错误地返回 'simple' —— 即使你正在编辑的是分组商品(Grouped Product)或可变商品(Variable Product)。这是因为 save_post_* 是 WordPress 原生钩子,仅传递 WP_Post 对象,而非已实例化的 WC_Product 对象,其 get_type() 方法无法正确读取 WooCommerce 的产品类型元数据。
✅ 正确做法是使用 WooCommerce 专用的生命周期钩子:
add_action('woocommerce_after_product_object_save', 'nd_update_group_product_attributes_func', 10, 2);该钩子在 WC_Product_Data_Store 完成持久化操作后触发,并直接传入已完全加载、类型明确的 WC_Product 实例(即 $product 参数),此时调用 $product->get_type() 将始终返回准确值(如 'grouped'、'variable' 等),且支持所有类型判断方法,例如 $product->is_type('grouped')。
以下是优化后的完整示例(含健壮性处理):
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) {
// 确保是有效产品对象且为分组商品
if (!$product || !is_a($product, 'WC_Product') || !$product->is_type('grouped')) {
return;
}
$child_ids = $product->get_children();
$all_bedrooms = array();
foreach ($child_ids as $child_id) {
$child = wc_get_product($child_id);
if ($child && $child->is_type('simple')) {
$bedrooms = $child->get_attribute('pa_bedrooms');
if (!empty($bedrooms)) {
$all_bedrooms = array_merge($all_bedrooms, (array) $bedrooms);
}
}
}
// 去重并同步到当前分组商品的 pa_bedrooms 分类法
$unique_bedrooms = array_unique($all_bedrooms);
if (!empty($unique_bedrooms)) {
wp_set_object_terms($product->get_id(), $unique_bedrooms, 'pa_bedrooms', false);
}
}⚠️ 注意事项:
- 不要依赖 $_POST 或 $post 全局变量推断产品类型,因其不可靠且易受表单提交顺序影响;
- woocommerce_after_product_object_save 是 WooCommerce 3.0+ 推荐的标准化钩子,兼容所有产品类型与数据存储层(如 WC_Product_Data_Store_CPT);
- 若需兼容旧版本(
- 在循环中调用 wc_get_product() 时,请注意性能;对大量子商品场景,建议批量查询优化(如 wc_get_products(['include' => $child_ids]))。
总结:获取真实产品类型的关键,在于使用 WooCommerce 原生对象生命周期钩子,而非 WordPress 通用钩子。woocommerce_after_product_object_save 提供了最及时、最准确的产品实例,是构建稳定、可维护 WooCommerce 扩展的基石实践。










