文章目录[隐藏]
实操指南:配置多币种价格展示的4个灵活技巧
引言:为什么多币种展示对现代电商至关重要
在全球化电商时代,面向国际客户的网站必须提供多币种价格展示功能。根据Statista的数据,超过70%的在线消费者更倾向于使用本地货币查看价格,这能显著提升转化率。对于基于WordPress的电商网站而言,实现灵活的多币种展示不仅提升用户体验,还能扩大国际市场覆盖。
WordPress作为全球最流行的内容管理系统,拥有丰富的插件生态和灵活的代码架构,为开发者提供了多种实现多币种展示的途径。本指南将深入探讨四种实用技巧,从简单插件配置到高级代码开发,帮助行业新人和程序员根据项目需求选择合适方案。
技巧一:利用WooCommerce多币种插件实现快速部署
1.1 插件选择与评估标准
对于刚入行的开发者或时间紧迫的项目,使用成熟插件是最快捷的解决方案。以下是几款优秀的WooCommerce多币种插件:
- Currency Switcher for WooCommerce:提供自动汇率更新和地理定位功能
- WooCommerce Multi-Currency:支持固定汇率和手动汇率设置
- Aelia Currency Switcher:企业级解决方案,支持多种定价策略
选择插件时应考虑以下因素:
- 汇率更新机制(自动/手动)
- 与当前主题和插件的兼容性
- 地理定位准确度
- 缓存处理机制
- 性能影响评估
1.2 插件配置最佳实践
以Currency Switcher for WooCommerce为例,以下是详细配置步骤:
// 示例:通过代码增强插件功能
add_filter('woocommerce_currency_switcher_settings', 'custom_currency_settings');
function custom_currency_settings($settings) {
// 添加自定义货币
$settings['additional_currencies'][] = array(
'currency' => 'CNY',
'rate' => 6.5,
'label' => '人民币'
);
// 设置默认显示货币
$settings['default_currency'] = 'USD';
// 启用地理定位
$settings['enable_geoip'] = true;
return $settings;
}
// 添加货币切换器到指定位置
add_action('woocommerce_before_add_to_cart_button', 'display_currency_switcher');
function display_currency_switcher() {
if (function_exists('currency_switcher_form')) {
currency_switcher_form();
}
}
1.3 性能优化与缓存策略
多币种插件可能影响网站性能,特别是当使用实时汇率时。以下优化建议:
- 实施缓存机制:缓存转换后的价格,避免每次页面加载都进行汇率计算
- 设置合理的更新频率:非关键货币可设置较长的汇率更新间隔
- 使用CDN地理定位:减轻服务器地理定位负担
- 异步加载汇率数据:避免阻塞页面渲染
技巧二:自定义汇率API集成与实时更新
2.1 选择可靠的汇率数据源
对于需要实时汇率或插件无法满足需求的项目,集成第三方汇率API是理想选择。以下是推荐的API服务:
- ExchangeRate-API:免费层提供1500次/月请求,支持170种货币
- Open Exchange Rates:提供灵活的付费方案,数据更新频繁
- CurrencyLayer:简单易用,提供实时和历史汇率数据
2.2 构建自定义汇率管理模块
以下代码展示如何创建自定义汇率管理功能:
// 汇率管理器类
class Custom_Exchange_Rate_Manager {
private $api_key;
private $base_currency;
private $cache_duration;
public function __construct($api_key, $base_currency = 'USD', $cache_duration = 3600) {
$this->api_key = $api_key;
$this->base_currency = $base_currency;
$this->cache_duration = $cache_duration;
}
// 获取实时汇率
public function get_live_rates($currencies = array()) {
$cache_key = 'custom_exchange_rates_' . md5(implode(',', $currencies));
$cached_rates = get_transient($cache_key);
if ($cached_rates !== false) {
return $cached_rates;
}
$api_url = add_query_arg(array(
'access_key' => $this->api_key,
'base' => $this->base_currency,
'symbols' => implode(',', $currencies)
), 'http://api.exchangeratesapi.io/v1/latest');
$response = wp_remote_get($api_url);
if (is_wp_error($response)) {
// 失败时使用备用数据源或缓存数据
return $this->get_fallback_rates($currencies);
}
$data = json_decode(wp_remote_retrieve_body($response), true);
if (isset($data['rates'])) {
set_transient($cache_key, $data['rates'], $this->cache_duration);
return $data['rates'];
}
return $this->get_fallback_rates($currencies);
}
// 备用汇率数据
private function get_fallback_rates($currencies) {
$default_rates = array(
'USD' => 1.0,
'EUR' => 0.85,
'GBP' => 0.73,
'JPY' => 110.5,
'CAD' => 1.25
);
$result = array();
foreach ($currencies as $currency) {
$result[$currency] = isset($default_rates[$currency]) ?
$default_rates[$currency] : 1.0;
}
return $result;
}
// 转换价格
public function convert_price($price, $from_currency, $to_currency) {
if ($from_currency === $to_currency) {
return $price;
}
$rates = $this->get_live_rates(array($from_currency, $to_currency));
if (!isset($rates[$from_currency]) || !isset($rates[$to_currency])) {
return $price;
}
// 转换为基准货币,再转换为目标货币
$base_price = $price / $rates[$from_currency];
return round($base_price * $rates[$to_currency], 2);
}
}
// 初始化汇率管理器
$exchange_manager = new Custom_Exchange_Rate_Manager('YOUR_API_KEY');
// 在WooCommerce中应用汇率转换
add_filter('woocommerce_product_get_price', 'custom_currency_conversion', 10, 2);
function custom_currency_conversion($price, $product) {
if (is_admin() || !is_numeric($price)) {
return $price;
}
global $exchange_manager;
// 获取用户选择的货币(可从会话或Cookie中获取)
$user_currency = isset($_COOKIE['user_currency']) ?
sanitize_text_field($_COOKIE['user_currency']) : 'USD';
// 如果用户货币不是商店默认货币,进行转换
$store_currency = get_woocommerce_currency();
if ($user_currency !== $store_currency) {
$price = $exchange_manager->convert_price($price, $store_currency, $user_currency);
}
return $price;
}
2.3 汇率更新与错误处理机制
为确保汇率数据的可靠性,需要实现以下机制:
- 定时任务更新:使用WP Cron定期更新汇率
- 失败重试逻辑:API请求失败时自动重试
- 数据验证:检查获取的汇率数据是否合理
- 降级方案:当所有API都失败时使用最后已知的有效汇率
// 设置定时任务更新汇率
add_action('wp', 'schedule_exchange_rate_updates');
function schedule_exchange_rate_updates() {
if (!wp_next_scheduled('update_exchange_rates_daily')) {
wp_schedule_event(time(), 'daily', 'update_exchange_rates_daily');
}
}
add_action('update_exchange_rates_daily', 'update_exchange_rates');
function update_exchange_rates() {
global $exchange_manager;
$currencies = array('USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD');
$rates = $exchange_manager->get_live_rates($currencies);
// 存储到数据库选项
update_option('custom_exchange_rates', $rates);
update_option('custom_exchange_rates_updated', current_time('mysql'));
}
技巧三:基于地理定位的智能货币切换
3.1 地理定位技术选择
根据用户地理位置自动显示当地货币能极大提升用户体验。以下是几种实现方式:
- IP地址定位:使用免费或付费IP地理定位数据库
- HTML5 Geolocation API:获取用户精确位置(需要用户授权)
- 混合方法:优先使用IP定位,失败时回退到默认货币
3.2 实现智能货币检测与切换
// 地理定位货币检测类
class Geo_Currency_Detector {
private $ip_api_service;
private $default_currency;
public function __construct($default_currency = 'USD') {
$this->default_currency = $default_currency;
$this->ip_api_service = 'http://ip-api.com/json/';
}
// 根据IP检测国家
public function detect_country_by_ip($ip = null) {
if ($ip === null) {
$ip = $this->get_user_ip();
}
$cache_key = 'geo_country_' . $ip;
$cached_country = get_transient($cache_key);
if ($cached_country !== false) {
return $cached_country;
}
$response = wp_remote_get($this->ip_api_service . $ip);
if (is_wp_error($response)) {
return false;
}
$data = json_decode(wp_remote_retrieve_body($response), true);
if (isset($data['countryCode'])) {
set_transient($cache_key, $data['countryCode'], DAY_IN_SECONDS);
return $data['countryCode'];
}
return false;
}
// 获取用户IP地址
private function get_user_ip() {
$ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED',
'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');
foreach ($ip_keys as $key) {
if (array_key_exists($key, $_SERVER) === true) {
foreach (explode(',', $_SERVER[$key]) as $ip) {
$ip = trim($ip);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
return $ip;
}
}
}
}
return $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
}
// 国家代码到货币的映射
public function country_to_currency($country_code) {
$country_currency_map = array(
'US' => 'USD', 'GB' => 'GBP', 'DE' => 'EUR', 'FR' => 'EUR',
'IT' => 'EUR', 'ES' => 'EUR', 'CA' => 'CAD', 'AU' => 'AUD',
'JP' => 'JPY', 'CN' => 'CNY', 'IN' => 'INR', 'BR' => 'BRL',
'RU' => 'RUB', 'KR' => 'KRW', 'MX' => 'MXN'
);
return isset($country_currency_map[$country_code]) ?
$country_currency_map[$country_code] : $this->default_currency;
}
// 检测并设置用户货币
public function detect_and_set_currency() {
// 检查是否已有用户选择的货币
if (isset($_COOKIE['user_selected_currency']) && $_COOKIE['user_selected_currency'] !== 'auto') {
return;
}
$country_code = $this->detect_country_by_ip();
if ($country_code) {
$currency = $this->country_to_currency($country_code);
// 设置会话或Cookie
if (!isset($_COOKIE['user_currency'])) {
setcookie('user_currency', $currency, time() + (30 * DAY_IN_SECONDS), '/');
$_COOKIE['user_currency'] = $currency;
}
}
}
}
// 初始化地理定位检测
add_action('init', 'init_geo_currency_detection');
function init_geo_currency_detection() {
$detector = new Geo_Currency_Detector();
$detector->detect_and_set_currency();
}
3.3 用户偏好与隐私考虑
在实现地理定位时,必须尊重用户隐私和选择权:
- 提供明确选项:允许用户手动选择货币,覆盖自动检测
- 隐私政策说明:明确告知用户如何使用位置数据
- GDPR合规:为欧盟用户提供适当的隐私保护
- 退出机制:提供简单的方法禁用地理定位功能
// 货币选择器小工具
add_action('widgets_init', 'register_currency_selector_widget');
function register_currency_selector_widget() {
register_widget('Currency_Selector_Widget');
}
class Currency_Selector_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'currency_selector',
__('货币选择器', 'text_domain'),
array('description' => __('允许用户选择偏好的货币', 'text_domain'))
);
}
public function widget($args, $instance) {
echo $args['before_widget'];
if (!empty($instance['title'])) {
echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
}
$available_currencies = array('USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD');
$current_currency = isset($_COOKIE['user_currency']) ? $_COOKIE['user_currency'] : 'USD';
echo '<form method="post" class="currency-selector-form">';
echo '<select name="selected_currency" class="currency-select">';
foreach ($available_currencies as $currency) {
$selected = ($currency === $current_currency) ? 'selected' : '';
echo '<option value="' . esc_attr($currency) . '" ' . $selected . '>' . esc_html($currency) . '</option>';
}
echo '<option value="auto">' . __('自动检测', 'text_domain') . '</option>';
echo '</select>';
wp_nonce_field('update_currency_preference', 'currency_nonce');
echo '<button type="submit" class="button currency-update-btn">' . __('更新', 'text_domain') . '</button>';
echo '</form>';
echo '<p class="currency-privacy-notice">' .
__('我们使用地理定位为您显示本地货币。您随时可以手动选择其他货币。', 'text_domain') .
'</p>';
echo $args['after_widget'];
}
public function update($new_instance, $old_instance) {
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
return $instance;
}
public function form($instance) {
$title = !empty($instance['title']) ? $instance['title'] : __('选择货币', 'text_domain');
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>">
<?php esc_attr_e('标题:', 'text_domain'); ?>
</label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>"
name="<?php echo esc_attr($this->get_field_name('title')); ?>"
type="text" value="<?php echo esc_attr($title); ?>">
</p>
<?php
}
}
// 处理货币选择表单提交
add_action('init', 'handle_currency_selection');
function handle_currency_selection() {
if (isset($_POST['selected_currency']) && isset($_POST['currency_nonce']) &&
wp_verify_nonce($_POST['currency_nonce'], 'update_currency_preference')) {
$selected_currency = sanitize_text_field($_POST['selected_currency']);
// 设置Cookie,有效期30天
setcookie('user_selected_currency', $selected_currency, time() + (30 * DAY_IN_SECONDS), '/');
if ($selected_currency === 'auto') {
// 如果选择自动检测,删除手动选择的货币Cookie
setcookie('user_currency', '', time() - 3600, '/');
unset($_COOKIE['user_currency']);
} else {
setcookie('user_currency', $selected_currency, time() + (30 * DAY_IN_SECONDS), '/');
$_COOKIE['user_currency'] = $selected_currency;
}
// 重定向回原页面,避免重复提交
wp_safe_redirect(remove_query_arg('updated', wp_get_referer()));
exit;
}
}
技巧四:高级定制与性能优化策略
4.1 多层级缓存架构设计
对于高流量网站,高效的缓存策略至关重要:
// 多级缓存管理器
class Multi_Currency_Cache_Manager {
private $cache_layers;
public function __construct() {
$this->cache_layers = array(
'transient' => true, // WordPress瞬态缓存
'object' => true, // 对象缓存
'static' => true // 静态变量缓存
);
// 初始化静态缓存数组
static $static_cache = array();
}
// 获取缓存数据
public function get($key, $group = 'currency') {
$cache_key = $group . '_' . $key;
// 1. 检查静态缓存
static $static_cache = array();
if ($this->cache_layers['static'] && isset($static_cache[$cache_key])) {
return $static_cache[$cache_key];
}
// 2. 检查对象缓存
if ($this->cache_layers['object']) {
$object_cache = wp_cache_get($cache_key, $group);
if ($object_cache !== false) {
// 填充静态缓存
$static_cache[$cache_key] = $object_cache;
return $object_cache;
}
}
// 3. 检查瞬态缓存
if ($this->cache_layers['transient']) {
$transient_cache = get_transient($cache_key);
if ($transient_cache !== false) {
// 填充上层缓存
wp_cache_set($cache_key, $transient_cache, $group, HOUR_IN_SECONDS);
$static_cache[$cache_key] = $transient_cache;
return $transient_cache;
}
}
return false;
}
// 设置缓存数据
public function set($key, $data, $group = 'currency', $expiration = HOUR_IN_SECONDS) {
$cache_key = $group . '_' . $key;
// 1. 设置静态缓存
static $static_cache = array();
if ($this->cache_layers['static']) {
$static_cache[$cache_key] = $data;
}
// 2. 设置对象缓存
if ($this->cache_layers['object']) {
wp_cache_set($cache_key, $data, $group, $expiration);
}
// 3. 设置瞬态缓存
if ($this->cache_layers['transient']) {
set_transient($cache_key, $data, $expiration);
}
return true;
}
// 清除缓存
public function delete($key, $group = 'currency') {
$cache_key = $group . '_' . $key;
// 清除所有层级的缓存
static $static_cache = array();
unset($static_cache[$cache_key]);
wp_cache_delete($cache_key, $group);
delete_transient($cache_key);
return true;
}
}
// 使用缓存管理器的价格转换函数
add_filter('woocommerce_product_get_price', 'cached_currency_conversion', 20, 2);
function cached_currency_conversion($price, $product) {
if (is_admin() || !is_numeric($price)) {
return $price;
}
$cache_manager = new Multi_Currency_Cache_Manager();
$user_currency = isset($_COOKIE['user_currency']) ?
sanitize_text_field($_COOKIE['user_currency']) : get_woocommerce_currency();
$store_currency = get_woocommerce_currency();
// 如果用户货币与商店货币相同,无需转换
if ($user_currency === $store_currency) {
return $price;
}
// 生成缓存键
$cache_key = md5("price_{$product->get_id()}_{$price}_{$store_currency}_{$user_currency}");
// 尝试从缓存获取转换后的价格
$cached_price = $cache_manager->get($cache_key, 'converted_prices');
if ($cached_price !== false) {
return $cached_price;
}
// 缓存未命中,进行实际转换
global $exchange_manager;
$converted_price = $exchange_manager->convert_price($price, $store_currency, $user_currency);
// 存储到缓存(价格变化不频繁,可缓存较长时间)
$cache_manager->set($cache_key, $converted_price, 'converted_prices', 6 * HOUR_IN_SECONDS);
return $converted_price;
}
### 4.2 批量处理与AJAX优化
对于产品列表页等需要大量价格转换的场景,批量处理能显著提升性能:
// 批量价格转换类
class Batch_Currency_Converter {
private $exchange_manager;
private $batch_size;
public function __construct($exchange_manager, $batch_size = 50) {
$this->exchange_manager = $exchange_manager;
$this->batch_size = $batch_size;
}
// 批量转换产品价格
public function convert_product_prices($products, $from_currency, $to_currency) {
$converted_products = array();
$batch_count = ceil(count($products) / $this->batch_size);
for ($i = 0; $i < $batch_count; $i++) {
$batch = array_slice($products, $i * $this->batch_size, $this->batch_size);
$converted_batch = $this->process_batch($batch, $from_currency, $to_currency);
$converted_products = array_merge($converted_products, $converted_batch);
// 避免超时,批量处理间添加微小延迟
if ($i < $batch_count - 1) {
usleep(100000); // 0.1秒延迟
}
}
return $converted_products;
}
private function process_batch($products, $from_currency, $to_currency) {
$converted = array();
foreach ($products as $product) {
if (is_object($product) && method_exists($product, 'get_price')) {
$original_price = $product->get_price();
$converted_price = $this->exchange_manager->convert_price(
$original_price,
$from_currency,
$to_currency
);
// 创建产品副本并设置转换后的价格
$converted_product = clone $product;
$converted_product->converted_price = $converted_price;
$converted_product->original_currency = $from_currency;
$converted_product->display_currency = $to_currency;
$converted[] = $converted_product;
}
}
return $converted;
}
}
// AJAX端点用于动态货币切换
add_action('wp_ajax_update_currency_display', 'ajax_update_currency_display');
add_action('wp_ajax_nopriv_update_currency_display', 'ajax_update_currency_display');
function ajax_update_currency_display() {
// 验证nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'currency_switch_nonce')) {
wp_die('安全验证失败');
}
$new_currency = sanitize_text_field($_POST['currency']);
$product_ids = isset($_POST['product_ids']) ? array_map('intval', $_POST['product_ids']) : array();
// 设置用户货币偏好
setcookie('user_currency', $new_currency, time() + (30 * DAY_IN_SECONDS), '/');
$_COOKIE['user_currency'] = $new_currency;
// 批量获取产品价格
$response_data = array(
'currency' => $new_currency,
'products' => array(),
'symbol' => get_woocommerce_currency_symbol($new_currency)
);
if (!empty($product_ids)) {
global $exchange_manager;
$converter = new Batch_Currency_Converter($exchange_manager);
$products = array();
foreach ($product_ids as $product_id) {
$product = wc_get_product($product_id);
if ($product) {
$products[] = $product;
}
}
$store_currency = get_woocommerce_currency();
$converted_products = $converter->convert_product_prices($products, $store_currency, $new_currency);
foreach ($converted_products as $product) {
$response_data['products'][$product->get_id()] = array(
'price' => wc_price($product->converted_price, array('currency' => $new_currency)),
'regular_price' => isset($product->regular_price) ?
wc_price($product->converted_price, array('currency' => $new_currency)) : '',
'sale_price' => isset($product->sale_price) ?
wc_price($product->converted_price, array('currency' => $new_currency)) : ''
);
}
}
wp_send_json_success($response_data);
}
// 在前端添加AJAX货币切换功能
add_action('wp_footer', 'add_currency_ajax_script');
function add_currency_ajax_script() {
if (!is_woocommerce() && !is_cart() && !is_checkout()) {
return;
}
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
// 货币切换处理
$('.currency-switcher').on('change', function() {
var newCurrency = $(this).val();
var productIds = [];
// 收集当前页面的产品ID
$('.product').each(function() {
var productId = $(this).data('product-id');
if (productId) {
productIds.push(productId);
}
});
// 显示加载状态
$('.price').addClass('updating').html('<span class="loading">...</span>');
// 发送AJAX请求
$.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'POST',
data: {
action: 'update_currency_display',
currency: newCurrency,
product_ids: productIds,
nonce: '<?php echo wp_create_nonce('currency_switch_nonce'); ?>'
},
success: function(response) {
if (response.success) {
// 更新价格显示
$.each(response.data.products, function(productId, prices) {
$('[data-product-id="' + productId + '"] .price').html(prices.price);
if (prices.regular_price) {
$('[data-product-id="' + productId + '"] .regular-price').html(prices.regular_price);
}
if (prices.sale_price) {
$('[data-product-id="' + productId + '"] .sale-price').html(prices.sale_price);
}
});
// 更新货币符号
$('.currency-symbol').text(response.data.symbol);
// 更新购物车中的价格(如果有)
updateCartPrices(newCurrency);
}
},
complete: function() {
$('.price').removeClass('updating');
}
});
});
function updateCartPrices(currency) {
// 这里可以添加购物车价格更新逻辑
// 可能需要重新加载购物车片段或发送另一个AJAX请求
}
});
</script>
<?php
}
### 4.3 数据库优化与索引策略
当产品数量庞大时,数据库优化变得至关重要:
// 数据库优化类
class Currency_DB_Optimizer {
// 创建汇率历史表
public static function create_exchange_rate_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'currency_exchange_rates';
$history_table_name = $wpdb->prefix . 'currency_rate_history';
// 主汇率表
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
base_currency varchar(3) NOT NULL,
target_currency varchar(3) NOT NULL,
exchange_rate decimal(12,6) NOT NULL,
last_updated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
source varchar(50) DEFAULT 'api',
is_active tinyint(1) DEFAULT 1,
PRIMARY KEY (id),
UNIQUE KEY currency_pair (base_currency, target_currency),
KEY last_updated (last_updated),
KEY is_active (is_active)
) $charset_collate;";
// 汇率历史表
$sql .= "CREATE TABLE IF NOT EXISTS $history_table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
base_currency varchar(3) NOT NULL,
target_currency varchar(3) NOT NULL,
exchange_rate decimal(12,6) NOT NULL,
recorded_at datetime DEFAULT CURRENT_TIMESTAMP,
source varchar(50) DEFAULT 'api',
PRIMARY KEY (id),
KEY currency_pair_date (base_currency, target_currency, recorded_at),
KEY recorded_at (recorded_at)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
// 批量更新汇率数据
public static function batch_update_rates($rates, $base_currency = 'USD') {
global $wpdb;
$table_name = $wpdb->prefix . 'currency_exchange_rates';
$values = array();
$placeholders = array();
$now = current_time('mysql');
foreach ($rates as $currency => $rate) {
if ($currency !== $base_currency) {
$values[] = $base_currency;
$values[] = $currency;
$values[] = floatval($rate);
$values[] = $now;
$placeholders[] = "(%s, %s, %f, %s)";
}
}
if (empty($values)) {
return false;
}
$query = "INSERT INTO $table_name
(base_currency, target_currency, exchange_rate, last_updated)
VALUES " . implode(', ', $placeholders) . "
ON DUPLICATE KEY UPDATE
exchange_rate = VALUES(exchange_rate),
last_updated = VALUES(last_updated)";
return $wpdb->query($wpdb->prepare($query, $values));
}
// 获取历史汇率数据用于分析
public static function get_rate_history($base_currency, $target_currency, $days = 30) {
global $wpdb;
$history_table_name = $wpdb->prefix . 'currency_rate_history';
$query = $wpdb->prepare(
"SELECT DATE(recorded_at) as date,
AVG(exchange_rate) as avg_rate,
MIN(exchange_rate) as min_rate,
MAX(exchange_rate) as max_rate
FROM $history_table_name
WHERE base_currency = %s
AND target_currency = %s
AND recorded_at >= DATE_SUB(NOW(), INTERVAL %d DAY)
GROUP BY DATE(recorded_at)
ORDER BY date DESC",
$base_currency,
$target_currency,
$days
);
return $wpdb->get_results($query);
}
// 清理旧数据
public static function cleanup_old_data($days_to_keep = 90) {
global $wpdb;
$history_table_name = $wpdb->prefix . 'currency_rate_history';
return $wpdb->query(
$wpdb->prepare(
"DELETE FROM $history_table_name
WHERE recorded_at < DATE_SUB(NOW(), INTERVAL %d DAY)",
$days_to_keep
)
);
}
}
// 在插件激活时创建表
register_activation_hook(__FILE__, array('Currency_DB_Optimizer', 'create_exchange_rate_tables'));
// 定期清理旧数据
add_action('currency_daily_maintenance', array('Currency_DB_Optimizer', 'cleanup_old_data'));
### 4.4 监控与日志记录
完善的监控系统能帮助及时发现和解决问题:
// 货币转换监控类
class Currency_Conversion_Monitor {
private static $instance;
private $log_table;
private function __construct() {
global $wpdb;
$this->log_table = $wpdb->prefix . 'currency_conversion_logs';
$this->create_log_table();
}
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function create_log_table() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS {$this->log_table} (
log_id bigint(20) NOT NULL AUTO_INCREMENT,
session_id varchar(32) NOT NULL,
user_id bigint(20) DEFAULT 0,
original_price decimal(12,2) NOT NULL,
converted_price decimal(12,2) NOT NULL,
from_currency varchar(3) NOT NULL,
to_currency varchar(3) NOT NULL,
exchange_rate decimal(12,6) NOT NULL,
conversion_source varchar(50) DEFAULT 'api',
ip_address varchar(45) DEFAULT '',
user_agent text,
page_url varchar(500) DEFAULT '',
conversion_time datetime DEFAULT CURRENT_TIMESTAMP,
response_time float DEFAULT 0,
success tinyint(1) DEFAULT 1,
error_message text,
cache_hit tinyint(1) DEFAULT 0,
PRIMARY KEY (log_id),
KEY session_id (session_id),
KEY conversion_time (conversion_time),
KEY currency_pair (from_currency, to_currency),
KEY success (success),
KEY user_id (user_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes
