You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress自定义WooCommerce插件添加新产品时无法设置价格

问题排查:新增WooCommerce Metal产品类型时价格为空的问题

我正在开发一款扩展WooCommerce的WordPress插件,新增了“Metal”产品类型及对应必填自定义字段。使用woocommerce_process_product_meta钩子保存元值,但仅在添加新产品时产品价格被设置为空字符串,更新产品时功能完全正常。相关代码如下:

add_action( 'woocommerce_process_product_meta', 'wm_save_fields' );

function wm_save_fields( $id ){
    if(isset($_POST['product-type']) && $_POST['product-type'] == 'metal') {

        $weight = $_POST['_metal_weight'];
        $margin = $_POST['_metal_margin'];

        if(
            !isset($weight) ||
            !isset($margin)
        ) {
            return;
        }

        $weight = ($weight == "") ? 0 : sanitize_text_field($_POST['_metal_weight']);
        $margin = ($margin == "") ? 0 : sanitize_text_field($_POST['_metal_margin']);

        $gold_price = get_option('wm_gold_price');

        $price = $weight * $gold_price;
        $margin_price = $price + (($margin / 100) * $price);
        $margin_price = number_format($margin_price, 2);

        update_post_meta( $id, 'wm_weight', $weight );
        update_post_meta( $id, 'wm_margin', $margin );

        if(get_post_meta( $id, '_price' )) {
            update_post_meta( $id, '_price', $margin_price );
        } else {
            add_post_meta( $id, '_price', $margin_price );
        }
    }
}

核心原因分析

  1. 钩子执行时机冲突:woocommerce_process_product_meta的默认执行优先级是10,而WooCommerce在创建新产品时,会默认将_price字段设为空值,这个操作的执行时机可能晚于你的代码,直接覆盖了你设置的价格。
  2. get_post_meta判断逻辑错误:get_post_meta($id, '_price')在新产品创建时会返回空数组(元数据不存在),但PHP中空数组在布尔判断中会被视为true,导致代码执行update_post_meta,但后续WooCommerce的默认逻辑又把价格清空。
  3. 价格格式兼容性问题:number_format返回带千分位的字符串(如1,234.56),而WooCommerce的价格字段需要浮点型或无千分位的字符串,可能导致识别异常。

修复方案

方案1:更换钩子,提前执行逻辑

使用woocommerce_new_product(创建新产品触发)和woocommerce_update_product(更新产品触发)两个钩子,确保你的代码在WooCommerce默认设置价格之前执行:

// 处理新产品创建
add_action( 'woocommerce_new_product', 'wm_save_fields_new', 10, 1 );
function wm_save_fields_new( $id ){
    wm_save_product_fields( $id );
}

// 处理产品更新
add_action( 'woocommerce_update_product', 'wm_save_fields_update', 10, 1 );
function wm_save_fields_update( $id ){
    wm_save_product_fields( $id );
}

// 通用处理函数
function wm_save_product_fields( $id ){
    if( isset($_POST['product-type']) && $_POST['product-type'] == 'metal' ) {

        // 严谨判断字段是否存在
        $weight = isset($_POST['_metal_weight']) ? $_POST['_metal_weight'] : '';
        $margin = isset($_POST['_metal_margin']) ? $_POST['_metal_margin'] : '';

        // 必填字段校验
        if( empty($weight) || empty($margin) ) {
            return;
        }

        // 清理并转换为数值类型
        $weight = floatval( sanitize_text_field($weight) );
        $margin = floatval( sanitize_text_field($margin) );
        $gold_price = floatval( get_option('wm_gold_price', 0) );

        // 计算价格,用round避免千分位问题
        $price = $weight * $gold_price;
        $margin_price = $price + (($margin / 100) * $price);
        $margin_price = round($margin_price, 2);

        // 保存自定义元数据
        update_post_meta( $id, 'wm_weight', $weight );
        update_post_meta( $id, 'wm_margin', $margin );

        // 直接更新价格,update_post_meta自动处理添加/更新
        update_post_meta( $id, '_price', $margin_price );
        // 同步更新_regular_price,保持WooCommerce数据一致性
        update_post_meta( $id, '_regular_price', $margin_price );
    }
}

方案2:提升原钩子的执行优先级

如果坚持使用woocommerce_process_product_meta,将优先级设为5(早于默认的10),确保代码先于WooCommerce的默认逻辑执行:

add_action( 'woocommerce_process_product_meta', 'wm_save_fields', 5, 1 );

function wm_save_fields( $id ){
    if(isset($_POST['product-type']) && $_POST['product-type'] == 'metal') {

        $weight = isset($_POST['_metal_weight']) ? sanitize_text_field($_POST['_metal_weight']) : 0;
        $margin = isset($_POST['_metal_margin']) ? sanitize_text_field($_POST['_metal_margin']) : 0;

        $weight = floatval($weight);
        $margin = floatval($margin);
        $gold_price = floatval( get_option('wm_gold_price', 0) );

        $price = $weight * $gold_price;
        $margin_price = $price + (($margin / 100) * $price);
        $margin_price = round($margin_price, 2);

        update_post_meta( $id, 'wm_weight', $weight );
        update_post_meta( $id, 'wm_margin', $margin );

        // 直接更新价格,无需判断是否存在
        update_post_meta( $id, '_price', $margin_price );
        update_post_meta( $id, '_regular_price', $margin_price );
    }
}

内容的提问来源于stack exchange,提问作者howtogeek24

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:35:16