WooCommerce价格筛选组件适配动态汇率价格问题求助
Alright, let's tackle this problem head-on: your plugin converts backend USD prices to a frontend display price using an exchange rate, but WooCommerce's built-in Price Filter is still relying on the raw USD values stored in the database. To fix this, we need to handle two critical pieces:
- Update the Price Filter widget's displayed min/max values to show converted prices (not raw USD)
- Convert the user-selected price range back to USD before WooCommerce runs its database query, so it matches the stored values
Here's how to adjust your existing code to make this work properly:
1. Fix the Price Filter's Displayed Min/Max Values
Your current code tries to reuse the custom_price function for filter values, but the hook signatures need tweaks, and we should add safeguards for invalid exchange rates. We'll also cover both widget and global price filter hooks:
// Adjust displayed min/max values for price filter widget and global filter add_filter('woocommerce_price_filter_widget_min_amount', 'convert_filter_price_amount', 99); add_filter('woocommerce_price_filter_widget_max_amount', 'convert_filter_price_amount', 99); add_filter('woocommerce_price_filter_min_amount', 'convert_filter_price_amount', 99); add_filter('woocommerce_price_filter_max_amount', 'convert_filter_price_amount', 99); function convert_filter_price_amount($amount) { $exchange_rate = get_option('kurs'); // Only convert if we have a valid positive exchange rate if (!empty($exchange_rate) && is_numeric($exchange_rate) && floatval($exchange_rate) > 0) { return floatval($amount) * floatval($exchange_rate); } // Fallback to original amount if rate is missing/invalid return $amount; }
2. Convert User-Selected Filter Range Back to Raw USD
Your existing filter function has the right idea, but we'll add better validation to avoid errors (like dividing by zero) and clean up the logic:
add_filter('woocommerce_product_query_meta_query', 'adjust_price_filter_query_for_exchange', 10, 2); function adjust_price_filter_query_for_exchange($meta_query, $query) { // Only run if price filter parameters exist if (!isset($_GET['min_price']) && !isset($_GET['max_price'])) { return $meta_query; } $exchange_rate = get_option('kurs'); // Skip if exchange rate is missing, non-numeric, or zero/negative if (empty($exchange_rate) || !is_numeric($exchange_rate) || floatval($exchange_rate) <= 0) { return $meta_query; } $rate = floatval($exchange_rate); // Convert user-selected min price back to raw USD if (isset($_GET['min_price']) && is_numeric($_GET['min_price']) && floatval($_GET['min_price']) > 0) { $raw_min = floatval($_GET['min_price']) / $rate; if (isset($meta_query['price_filter']['value'][0])) { $meta_query['price_filter']['value'][0] = $raw_min; } } // Convert user-selected max price back to raw USD if (isset($_GET['max_price']) && is_numeric($_GET['max_price'])) { $raw_max = floatval($_GET['max_price']) / $rate; if (isset($meta_query['price_filter']['value'][1])) { $meta_query['price_filter']['value'][1] = $raw_max; } } return $meta_query; }
3. Keep Your Existing Price Conversion Logic (With Minor Tweaks)
Your custom_price function works for frontend display, but we'll update the function signature to match WooCommerce's hook parameters (some hooks pass a $product argument, even if we don't use it):
// Simple product price conversion add_filter('woocommerce_product_get_price', 'custom_price', 99, 2 ); add_filter('woocommerce_product_get_regular_price', 'custom_price', 99, 2 ); // Variable product variation price conversion add_filter('woocommerce_product_variation_get_regular_price', 'custom_price', 99, 2 ); add_filter('woocommerce_product_variation_get_price', 'custom_price', 99, 2 ); // Variation prices (handles cached variation prices) add_filter('woocommerce_variation_prices_price', 'custom_price', 99, 3 ); add_filter('woocommerce_variation_prices_regular_price', 'custom_price', 99, 3 ); add_filter('woocommerce_variation_prices_sale_price', 'custom_price', 99, 3 ); function custom_price($price, $product = null) { $float_price = floatval($price); $exchange_rate = get_option('kurs'); return !empty($exchange_rate) && is_numeric($exchange_rate) ? $float_price * floatval($exchange_rate) : $float_price; }
4. Extra: Add Exchange Rate Validation (Optional but Recommended)
To prevent invalid values from breaking your price calculations, add a sanitization filter for the exchange rate setting:
add_filter('sanitize_option_kurs', 'sanitize_exchange_rate_setting'); function sanitize_exchange_rate_setting($value) { // Ensure the value is a positive number; empty it if not $sanitized = floatval($value); return $sanitized > 0 ? $sanitized : ''; }
How This Works Together
- The Price Filter widget now displays converted prices (e.g., if your rate is 7, a $10 product shows as 70, so the filter's min/max will reflect this)
- When a user selects a range like 70-140, the code converts that back to $10-$20 before WooCommerce queries the database, so it returns the correct products
- Your existing variation price caching fix (
add_price_multiplier_to_variation_prices_hash) is still valid—keep that in place to avoid cached variation prices not updating when you change the exchange rate
内容的提问来源于stack exchange,提问作者vekeg31838

