WooCommerce黄金价格调整插件变量产品变体选择问题及报错求助
Gold Price Adjuster插件问题修复
问题概述
开发了一款名为Gold Price Adjuster的WooCommerce插件,功能为管理员设置每克黄金价格,产品根据自身重量计算最终价格。目前遇到两个问题:
- 变量产品仅显示价格区间,无法选择变体
- 修改代码时出现报错
问题原因
- 变量产品变体选择失效:原代码中
gpa_adjust_variable_price_range函数错误使用array_search获取变体ID,当多个变体价格相同时会返回第一个匹配的ID,导致价格计算逻辑混乱,同时未正确处理WooCommerce变量产品的前端变体加载逻辑。 - 代码报错:原代码中
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); ?>
修复说明
解决变量产品变体无法选择问题:
- 新增
woocommerce_get_variation_prices_array钩子,直接修改变体价格数组,确保前端加载变体时能获取正确的调整后价格,修复变体选择失效问题。 - 原
gpa_adjust_variable_price_range函数改为遍历所有变体计算价格区间,避免array_search导致的ID匹配错误。
- 新增
解决代码报错问题:
- 在设置注册时添加
sanitize_callback,确保gpa_gold_price始终是数值类型,避免字符串转数值错误。 - 将设置页面的输入框改为
number类型,限制输入为数值,减少错误输入。 - 在所有产品/变体操作前增加存在性检查,避免调用不存在对象的方法。
- 在设置注册时添加
内容的提问来源于stack exchange,提问作者David Amagid
相关产品推荐
相关产品推荐

