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

WooCommerce黄金价格调整插件变量产品变体选择问题及报错求助

Gold Price Adjuster插件问题修复

问题概述

开发了一款名为Gold Price Adjuster的WooCommerce插件,功能为管理员设置每克黄金价格,产品根据自身重量计算最终价格。目前遇到两个问题:

  • 变量产品仅显示价格区间,无法选择变体
  • 修改代码时出现报错

问题原因

  1. 变量产品变体选择失效:原代码中gpa_adjust_variable_price_range函数错误使用array_search获取变体ID,当多个变体价格相同时会返回第一个匹配的ID,导致价格计算逻辑混乱,同时未正确处理WooCommerce变量产品的前端变体加载逻辑。
  2. 代码报错:原代码中wc_get_product(array_search(...))可能返回false,后续调用$variation->is_type('variation')会触发致命错误,因为对象不存在。

修复后的完整代码

<?php
/*
Plugin Name: Gold Price Adjuster
Description: Adjusts product prices based on gold price per gram.
Version: 2.0.1
Author: David Amagid
*/

// 创建设置页面
function gpa_create_settings_page() {
    add_menu_page(
        'Gold Price Settings',
        'Gold Price',
        'manage_options',
        'gold-price-settings',
        'gpa_render_settings_page',
        'dashicons-admin-generic',
        100
    );
}
add_action('admin_menu', 'gpa_create_settings_page');

function gpa_render_settings_page() {
    ?>
    <div class="wrap">
        <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
        <form method="post" action="options.php">
            <?php
            settings_fields('gpa_options_group');
            do_settings_sections('gold-price-settings');
            submit_button();
            ?>
        </form>
    </div>
    <?php
}

function gpa_register_settings() {
    register_setting('gpa_options_group', 'gpa_gold_price', [
        'sanitize_callback' => 'floatval', // 确保输入为数值
        'default' => 0
    ]);
    add_settings_section('gpa_main_section', 'Gold Price Settings', null, 'gold-price-settings');
    add_settings_field('gpa_gold_price_field', 'Gold Price Per Gram', 'gpa_gold_price_field_callback', 'gold-price-settings', 'gpa_main_section');
}
add_action('admin_init', 'gpa_register_settings');

function gpa_gold_price_field_callback() {
    $gold_price = get_option('gpa_gold_price', 0);
    echo '<input type="number" step="0.01" id="gpa_gold_price" name="gpa_gold_price" value="' . esc_attr($gold_price) . '" />';
}

// 调整简单产品价格
function gpa_adjust_simple_product_price($price, $product) {
    if (!$product->is_type('simple')) {
        return $price;
    }
    
    $gold_price = (float)get_option('gpa_gold_price', 0);
    $weight = (float)$product->get_weight();
    
    if ($gold_price > 0 && $weight > 0) {
        $price = floatval($price) + ($weight * $gold_price);
    }
    
    return $price;
}

// 调整变体产品价格
function gpa_adjust_variation_price($price, $variation) {
    if (!$variation->is_type('variation')) {
        return $price;
    }
    
    static $adjusted_prices = [];
    $variation_id = $variation->get_id();
    
    if (isset($adjusted_prices[$variation_id])) {
        return $adjusted_prices[$variation_id];
    }
    
    $gold_price = (float)get_option('gpa_gold_price', 0);
    $variation_weight = (float)$variation->get_weight();
    
    if ($gold_price > 0 && $variation_weight > 0) {
        $price = floatval($price) + ($variation_weight * $gold_price);
        $adjusted_prices[$variation_id] = $price;
    }
    
    return $price;
}

// 正确调整变量产品价格区间
function gpa_adjust_variable_price_range($price_html, $product) {
    if (!$product->is_type('variable')) {
        return $price_html;
    }
    
    $gold_price = (float)get_option('gpa_gold_price', 0);
    if ($gold_price <= 0) {
        return $price_html;
    }
    
    $min_price = PHP_FLOAT_MAX;
    $max_price = PHP_FLOAT_MIN;
    
    // 遍历所有变体计算调整后价格
    foreach ($product->get_available_variations() as $variation_data) {
        $variation = wc_get_product($variation_data['variation_id']);
        if (!$variation) continue;
        
        $original_price = (float)$variation->get_price();
        $weight = (float)$variation->get_weight();
        
        if ($weight <= 0) {
            $adjusted_price = $original_price;
        } else {
            $adjusted_price = $original_price + ($weight * $gold_price);
        }
        
        if ($adjusted_price < $min_price) $min_price = $adjusted_price;
        if ($adjusted_price > $max_price) $max_price = $adjusted_price;
    }
    
    // 处理所有变体都无重量的情况
    if ($min_price === PHP_FLOAT_MAX) {
        return $price_html;
    }
    
    return wc_price($min_price) . ' - ' . wc_price($max_price);
}

// 修复变量产品变体价格加载逻辑,确保前端能获取正确的调整后价格
function gpa_adjust_variation_prices_array($prices, $product, $for_display) {
    $gold_price = (float)get_option('gpa_gold_price', 0);
    if ($gold_price <= 0) {
        return $prices;
    }
    
    foreach ($prices['price'] as $variation_id => &$price) {
        $variation = wc_get_product($variation_id);
        if (!$variation || !$variation->is_type('variation')) continue;
        
        $weight = (float)$variation->get_weight();
        if ($weight > 0) {
            $price = floatval($price) + ($weight * $gold_price);
        }
    }
    
    // 更新常规价格数组
    foreach ($prices['regular_price'] as $variation_id => &$price) {
        $variation = wc_get_product($variation_id);
        if (!$variation || !$variation->is_type('variation')) continue;
        
        $weight = (float)$variation->get_weight();
        if ($weight > 0) {
            $price = floatval($price) + ($weight * $gold_price);
        }
    }
    
    return $prices;
}

// 钩子调整
add_filter('woocommerce_product_get_price', 'gpa_adjust_simple_product_price', 10, 2);
add_filter('woocommerce_product_variation_get_price', 'gpa_adjust_variation_price', 10, 2);

add_filter('woocommerce_product_get_regular_price', 'gpa_adjust_simple_product_price', 10, 2);
add_filter('woocommerce_product_variation_get_regular_price', 'gpa_adjust_variation_price', 10, 2);

// 替换原有的价格区间钩子,新增变体价格数组钩子
add_filter('woocommerce_variable_price_html', 'gpa_adjust_variable_price_range', 10, 2);
add_filter('woocommerce_get_variation_prices_array', 'gpa_adjust_variation_prices_array', 10, 3);
?>

修复说明

  1. 解决变量产品变体无法选择问题:

    • 新增woocommerce_get_variation_prices_array钩子,直接修改变体价格数组,确保前端加载变体时能获取正确的调整后价格,修复变体选择失效问题。
    • 原gpa_adjust_variable_price_range函数改为遍历所有变体计算价格区间,避免array_search导致的ID匹配错误。
  2. 解决代码报错问题:

    • 在设置注册时添加sanitize_callback,确保gpa_gold_price始终是数值类型,避免字符串转数值错误。
    • 将设置页面的输入框改为number类型,限制输入为数值,减少错误输入。
    • 在所有产品/变体操作前增加存在性检查,避免调用不存在对象的方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:36:01