
本文介绍在 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 扩展的基石实践。