WooCommerce变量产品自定义字段取值及函数间传值问题
解决WooCommerce自定义变量字段获取与函数间传值问题
嘿,我来帮你搞定这个问题!你已经成功在WooCommerce变量产品中创建了自定义字段_num_cubic_var,接下来我们一步步解决你的两个核心需求:
一、在ut_before_calculate_totals中获取_num_cubic_var的值
在购物车总价计算的函数里,每个购物车项都包含了对应的变体ID,你可以直接通过这个ID拉取自定义字段的值。我帮你优化了原函数,同时补上了必要的钩子挂载和防重复计算的判断(这是WooCommerce开发的最佳实践):
add_action( 'woocommerce_before_calculate_totals', 'ut_before_calculate_totals', 10, 1 ); function ut_before_calculate_totals( $cart_obj ) { // 避免后台重复触发计算(仅在前端或AJAX请求时执行) if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { return; } foreach( $cart_obj->get_cart() as $key => $value ) { // 获取当前购物车项对应的变体ID $variation_id = $value['data']->get_id(); // 拉取自定义字段值 $num_cubic_var = get_post_meta( $variation_id, '_num_cubic_var', true ); // 这里可以用$num_cubic_var做你需要的业务逻辑,比如结合它调整价格 if ( ! empty( $num_cubic_var ) ) { // 用WooCommerce内置方法获取价格(比直接读元数据更可靠) $base_price = $value['data']->get_sale_price() ? $value['data']->get_sale_price() : $value['data']->get_regular_price(); // 结合自定义字段计算新价格 $adjusted_price = $base_price * $num_cubic_var; $value['data']->set_price( $adjusted_price ); } } }
二、函数之间传递值的几种实用方式
在WordPress/WooCommerce生态里,有几种常用的函数间传值方案,你可以根据场景选择:
1. 全局变量(简单但需谨慎)
适合快速临时传值,但要注意命名冲突问题:
// 在第一个函数中设置全局变量 function set_cubic_value() { global $shared_cubic_value; $shared_cubic_value = get_post_meta( get_the_ID(), '_num_cubic_var', true ); } // 在第二个函数中获取全局变量 function use_cubic_value() { global $shared_cubic_value; if ( isset( $shared_cubic_value ) ) { // 这里使用值做逻辑处理 echo $shared_cubic_value; } }
2. WooCommerce会话(适合购物车/用户场景)
如果值和当前用户或购物车相关,用WC会话存储更安全:
// 保存值到会话 function save_cubic_to_session( $variation_id ) { if ( WC()->session->has_session() || is_user_logged_in() ) { $num_cubic_var = get_post_meta( $variation_id, '_num_cubic_var', true ); WC()->session->set( 'user_selected_cubic', $num_cubic_var ); } } // 从会话中读取值 function get_cubic_from_session() { $num_cubic_var = WC()->session->get( 'user_selected_cubic' ); if ( ! empty( $num_cubic_var ) ) { // 使用值做业务逻辑 } }
3. 钩子参数传递(最推荐的WordPress方式)
通过自定义钩子传递参数,完全符合WordPress的设计理念,避免全局变量的隐患:
// 在某个函数中触发自定义钩子并传递值 function trigger_custom_hook() { $variation_id = get_the_ID(); $num_cubic_var = get_post_meta( $variation_id, '_num_cubic_var', true ); // 触发钩子并传递参数 do_action( 'custom_cubic_value_ready', $num_cubic_var ); } // 监听钩子并接收参数 add_action( 'custom_cubic_value_ready', 'handle_cubic_value', 10, 1 ); function handle_cubic_value( $num_cubic_var ) { // 直接使用传递过来的$num_cubic_var echo "当前立方值:{$num_cubic_var}"; }
4. 静态类变量(适合复杂业务场景)
用类的静态变量规范管理共享值,适合多函数联动的复杂逻辑:
class CubicValueManager { public static $current_cubic_value; // 设置值 public static function set_value( $variation_id ) { self::$current_cubic_value = get_post_meta( $variation_id, '_num_cubic_var', true ); } // 获取值 public static function get_value() { return self::$current_cubic_value; } } // 使用示例:设置值 CubicValueManager::set_value( get_the_ID() ); // 使用示例:获取值 $cubic_value = CubicValueManager::get_value();
三、整合优化你的完整代码
最后我把你所有的代码整合优化了一遍,确保逻辑更严谨、写法更规范:
// 添加自定义字段到变量产品编辑页面 add_action( 'woocommerce_product_after_variable_attributes', 'num_cubicmeters_fields', 10, 3 ); function num_cubicmeters_fields( $loop, $variation_data, $variation ) { woocommerce_wp_text_input( array( 'id' => '_num_cubic_var[' . $variation->ID . ']', 'label' => 'Количество кубометров', 'description' => 'Укажи количество кубометров', 'desc_tip' => 'true', 'placeholder' => 'Количество кубометров, м3', 'type' => 'number', 'custom_attributes' => array( 'step' => 'any', 'min' => '0', ), 'value' => get_post_meta( $variation->ID, '_num_cubic_var', true ), ) ); } // 保存自定义字段值(增加空值处理) add_action( 'woocommerce_save_product_variation', 'art_save_variation_settings_fields', 10, 2 ); function art_save_variation_settings_fields( $post_id ) { if ( isset( $_POST['_num_cubic_var'][ $post_id ] ) && ! empty( $_POST['_num_cubic_var'][ $post_id ] ) ) { update_post_meta( $post_id, '_num_cubic_var', esc_attr( $_POST['_num_cubic_var'][ $post_id ] ) ); } else { // 若值为空则删除元数据,避免冗余 delete_post_meta( $post_id, '_num_cubic_var' ); } } // 加载自定义字段到前端变体数据(优化HTML拼接和转义) add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' ); function load_variation_settings_fields( $variations ) { $variations_num_cubic = get_post_meta( $variations['variation_id'], '_num_cubic_var', true ); if ( ! empty( $variations_num_cubic ) ) { $variations['_num_cubic_var'] = sprintf( '<div class="num-cubicmeters-prod"><span>Количество Кубометров</span>%s м3</div>', esc_html( $variations_num_cubic ) ); } return $variations; } // 购物车计算总价时获取自定义字段并处理 add_action( 'woocommerce_before_calculate_totals', 'ut_before_calculate_totals', 10, 1 ); function ut_before_calculate_totals( $cart_obj ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { return; } foreach( $cart_obj->get_cart() as $key => $value ) { $variation_id = $value['data']->get_id(); $num_cubic_var = get_post_meta( $variation_id, '_num_cubic_var', true ); if ( ! empty( $num_cubic_var ) ) { $base_price = $value['data']->get_sale_price() ?: $value['data']->get_regular_price(); $adjusted_price = $base_price * $num_cubic_var; $value['data']->set_price( $adjusted_price ); } } }
内容的提问来源于stack exchange,提问作者Cdelphi78
相关产品推荐
相关产品推荐

