文章目录[隐藏]
WordPress文创插件柔性库存同步技术详解
引言:文创电商的库存管理挑战
在文创电商领域,库存管理面临着独特的挑战。文创产品往往具有限量发售、预售周期长、生产批次不固定等特点,传统的库存管理系统难以适应这种灵活性需求。WordPress作为文创创业者常用的建站平台,其电商插件需要具备更智能的库存同步机制。本文将深入探讨一种柔性库存同步技术,帮助文创电商实现多平台、多仓库库存的智能管理。
柔性库存同步的核心概念
柔性库存同步是一种动态、自适应的库存管理方法,它不同于传统的硬性同步(即实时完全一致),而是允许在不同销售渠道之间设置缓冲区和优先级规则。这种技术特别适合文创产品,因为它可以:
- 处理预售和预订订单
- 管理限量版产品的分配
- 适应生产周期不固定的情况
- 处理多渠道销售时的库存冲突
技术架构设计
数据库结构设计
<?php
/**
* WordPress文创插件库存同步数据库表结构
*/
global $wpdb;
// 主库存表
$sql_main_stock = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}culture_stock_main (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
product_id BIGINT(20) UNSIGNED NOT NULL,
physical_stock INT(11) NOT NULL DEFAULT 0 COMMENT '物理库存',
available_stock INT(11) NOT NULL DEFAULT 0 COMMENT '可用库存',
reserved_stock INT(11) NOT NULL DEFAULT 0 COMMENT '预留库存',
preorder_stock INT(11) NOT NULL DEFAULT 0 COMMENT '预售库存',
min_threshold INT(11) NOT NULL DEFAULT 5 COMMENT '库存预警阈值',
sync_status TINYINT(1) NOT NULL DEFAULT 0 COMMENT '同步状态:0-未同步,1-已同步',
last_synced TIMESTAMP NULL DEFAULT NULL COMMENT '最后同步时间',
PRIMARY KEY (id),
KEY product_id (product_id),
KEY sync_status (sync_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
// 渠道库存表
$sql_channel_stock = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}culture_stock_channels (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
main_stock_id BIGINT(20) UNSIGNED NOT NULL,
channel_name VARCHAR(100) NOT NULL COMMENT '渠道名称:woocommerce,taobao,wechat等',
channel_product_id VARCHAR(255) DEFAULT NULL COMMENT '渠道商品ID',
allocated_stock INT(11) NOT NULL DEFAULT 0 COMMENT '分配库存',
buffer_stock INT(11) NOT NULL DEFAULT 0 COMMENT '缓冲库存',
priority TINYINT(2) NOT NULL DEFAULT 1 COMMENT '渠道优先级(1-10)',
auto_replenish TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否自动补货',
last_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY main_stock_id (main_stock_id),
KEY channel_name (channel_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
// 库存同步日志表
$sql_sync_log = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}culture_stock_sync_log (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
product_id BIGINT(20) UNSIGNED NOT NULL,
channel_from VARCHAR(100) DEFAULT NULL COMMENT '来源渠道',
channel_to VARCHAR(100) DEFAULT NULL COMMENT '目标渠道',
operation_type VARCHAR(50) NOT NULL COMMENT '操作类型:allocate, sync, adjust',
quantity_change INT(11) NOT NULL COMMENT '库存变化量',
old_value INT(11) DEFAULT NULL COMMENT '旧值',
new_value INT(11) DEFAULT NULL COMMENT '新值',
sync_result TINYINT(1) NOT NULL COMMENT '同步结果:0-失败,1-成功',
error_message TEXT DEFAULT NULL COMMENT '错误信息',
performed_by BIGINT(20) UNSIGNED DEFAULT NULL COMMENT '操作者',
performed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY product_id (product_id),
KEY performed_at (performed_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
// 执行创建表
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_main_stock);
dbDelta($sql_channel_stock);
dbDelta($sql_sync_log);
?>
库存同步算法实现
<?php
/**
* 柔性库存同步核心类
*/
class FlexibleStockSync {
private $product_id;
private $main_stock;
private $channel_stocks;
/**
* 构造函数
* @param int $product_id 产品ID
*/
public function __construct($product_id) {
$this->product_id = $product_id;
$this->load_stock_data();
}
/**
* 加载库存数据
*/
private function load_stock_data() {
global $wpdb;
// 加载主库存
$this->main_stock = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}culture_stock_main WHERE product_id = %d",
$this->product_id
));
// 加载渠道库存
$this->channel_stocks = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}culture_stock_channels WHERE main_stock_id = %d ORDER BY priority DESC",
$this->main_stock->id
));
}
/**
* 智能库存分配算法
* @param string $channel 渠道名称
* @param int $requested_qty 请求数量
* @return array 分配结果
*/
public function allocate_stock($channel, $requested_qty) {
$channel_stock = $this->get_channel_stock($channel);
if (!$channel_stock) {
return $this->create_error_response("渠道不存在");
}
// 检查渠道可用库存
$channel_available = $channel_stock->allocated_stock - $channel_stock->buffer_stock;
if ($channel_available >= $requested_qty) {
// 渠道库存充足,直接分配
return $this->allocate_from_channel($channel_stock, $requested_qty);
} else {
// 渠道库存不足,需要从主库存或其他渠道调配
return $this->redistribute_stock($channel, $requested_qty);
}
}
/**
* 从渠道直接分配库存
*/
private function allocate_from_channel($channel_stock, $quantity) {
global $wpdb;
$wpdb->update(
"{$wpdb->prefix}culture_stock_channels",
array('allocated_stock' => $channel_stock->allocated_stock - $quantity),
array('id' => $channel_stock->id),
array('%d'),
array('%d')
);
// 记录同步日志
$this->log_sync_operation(
$this->product_id,
'direct_allocation',
$channel_stock->channel_name,
$quantity,
1
);
return array(
'success' => true,
'allocated' => $quantity,
'source' => 'channel_direct',
'remaining' => $channel_stock->allocated_stock - $quantity
);
}
/**
* 重新分配库存(柔性同步核心)
*/
private function redistribute_stock($target_channel, $required_qty) {
global $wpdb;
$target_channel_data = $this->get_channel_stock($target_channel);
$available_from_main = $this->calculate_available_main_stock();
// 计算需要从其他渠道调配的数量
$needed_from_others = $required_qty -
($target_channel_data->allocated_stock - $target_channel_data->buffer_stock);
if ($available_from_main >= $needed_from_others) {
// 主库存充足,从主库存调配
return $this->allocate_from_main_stock($target_channel, $needed_from_others);
} else {
// 需要从其他渠道借用库存
return $this->borrow_from_other_channels($target_channel, $needed_from_others);
}
}
/**
* 从其他渠道借用库存(柔性策略)
*/
private function borrow_from_other_channels($target_channel, $needed_qty) {
global $wpdb;
$borrowed_channels = array();
$remaining_needed = $needed_qty;
// 按优先级从低到高借用库存(优先保护高优先级渠道)
usort($this->channel_stocks, function($a, $b) {
return $a->priority - $b->priority;
});
foreach ($this->channel_stocks as $source_channel) {
if ($source_channel->channel_name === $target_channel) {
continue; // 跳过目标渠道
}
// 计算可借用的库存(保留缓冲库存)
$available_to_borrow = max(0,
$source_channel->allocated_stock - $source_channel->buffer_stock - 1
);
if ($available_to_borrow > 0) {
$borrow_amount = min($available_to_borrow, $remaining_needed);
// 更新源渠道库存
$wpdb->update(
"{$wpdb->prefix}culture_stock_channels",
array('allocated_stock' => $source_channel->allocated_stock - $borrow_amount),
array('id' => $source_channel->id),
array('%d'),
array('%d')
);
// 更新目标渠道库存
$target_channel_data = $this->get_channel_stock($target_channel);
$wpdb->update(
"{$wpdb->prefix}culture_stock_channels",
array('allocated_stock' => $target_channel_data->allocated_stock + $borrow_amount),
array('channel_name' => $target_channel),
array('%d'),
array('%s')
);
$borrowed_channels[] = array(
'from' => $source_channel->channel_name,
'amount' => $borrow_amount
);
$remaining_needed -= $borrow_amount;
// 记录借用日志
$this->log_sync_operation(
$this->product_id,
'channel_borrow',
$source_channel->channel_name,
$borrow_amount,
1,
$target_channel
);
if ($remaining_needed <= 0) {
break;
}
}
}
if ($remaining_needed > 0) {
// 库存不足,部分分配
return array(
'success' => true,
'allocated' => $needed_qty - $remaining_needed,
'borrowed_from' => $borrowed_channels,
'partial' => true,
'message' => '库存不足,已部分分配'
);
}
return array(
'success' => true,
'allocated' => $needed_qty,
'borrowed_from' => $borrowed_channels,
'partial' => false
);
}
/**
* 记录同步操作
*/
private function log_sync_operation($product_id, $operation, $channel, $quantity, $result, $target_channel = null) {
global $wpdb;
$wpdb->insert(
"{$wpdb->prefix}culture_stock_sync_log",
array(
'product_id' => $product_id,
'channel_from' => $channel,
'channel_to' => $target_channel,
'operation_type' => $operation,
'quantity_change' => $quantity,
'sync_result' => $result,
'performed_by' => get_current_user_id() ?: null
),
array('%d', '%s', '%s', '%s', '%d', '%d', '%d')
);
}
// ... 其他辅助方法
}
?>
与WooCommerce的集成实现
<?php
/**
* WooCommerce库存同步适配器
*/
class WooCommerceStockAdapter {
/**
* 监听WooCommerce订单创建事件
*/
public static function init() {
// 订单创建时减少库存
add_action('woocommerce_new_order', array(__CLASS__, 'on_new_order'), 10, 1);
// 订单状态变化时调整库存
add_action('woocommerce_order_status_changed', array(__CLASS__, 'on_order_status_change'), 10, 3);
// 同步WooCommerce产品库存
add_action('save_post_product', array(__CLASS__, 'sync_product_stock'), 10, 3);
}
/**
* 处理新订单
*/
public static function on_new_order($order_id) {
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
// 使用柔性库存同步
$stock_sync = new FlexibleStockSync($product_id);
$result = $stock_sync->allocate_stock('woocommerce', $quantity);
if ($result['success']) {
// 更新WooCommerce库存显示
self::update_woocommerce_stock_display($product_id, $result['allocated']);
// 如果库存低于阈值,触发预警
if (isset($result['partial']) && $result['partial']) {
self::trigger_low_stock_alert($product_id);
}
}
}
}
/**
* 订单状态变化处理
*/
public static function on_order_status_change($order_id, $old_status, $new_status) {
$order = wc_get_order($order_id);
// 订单取消或退款时恢复库存
if (in_array($new_status, array('cancelled', 'refunded'))) {
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
// 恢复库存
self::restore_stock($product_id, $quantity, 'woocommerce');
}
}
}
/**
* 恢复库存
*/
private static function restore_stock($product_id, $quantity, $channel) {
global $wpdb;
// 更新渠道库存
$wpdb->query($wpdb->prepare(
"UPDATE {$wpdb->prefix}culture_stock_channels
SET allocated_stock = allocated_stock + %d
WHERE channel_name = %s AND main_stock_id IN (
SELECT id FROM {$wpdb->prefix}culture_stock_main WHERE product_id = %d
)",
$quantity,
$channel,
$product_id
));
// 记录恢复操作
$wpdb->insert(
"{$wpdb->prefix}culture_stock_sync_log",
array(
'product_id' => $product_id,
'channel_from' => $channel,
'operation_type' => 'restore',
'quantity_change' => $quantity,
'sync_result' => 1
)
);
}
}
?>
管理界面与配置
后台管理界面实现
<?php
/**
* 库存同步管理界面
*/
class StockSyncAdminInterface {
/**
* 添加管理菜单
*/
public static function add_admin_menu() {
add_menu_page(
'文创库存管理',
'库存同步',
'manage_options',
'culture-stock-sync',
array(__CLASS__, 'render_admin_page'),
'dashicons-archive',
56
);
// 添加子菜单
add_submenu_page(
'culture-stock-sync',
'渠道配置',
'渠道配置',
'manage_options',
'culture-stock-channels',
array(__CLASS__, 'render_channels_page')
);
add_submenu_page(
'culture-stock-sync',
'同步日志',
'同步日志',
'manage_options',
'culture-stock-logs',
array(__CLASS__, 'render_logs_page')
);
}
/**
* 渲染主管理页面
*/
public static function render_admin_page() {
?>
<div class="wrap">
<h1>文创产品库存同步管理</h1>
<div class="stock-overview">
<h2>库存概览</h2>
<div class="stock-stats">
<?php self::display_stock_statistics(); ?>
</div>
</div>
<div class="sync-controls">
<h2>手动同步控制</h2>
<form method="post" action="">
<?php wp_nonce_field('manual_sync_action', 'sync_nonce'); ?>
<p>
<label for="sync_scope">同步范围:</label>
<select name="sync_scope" id="sync_scope">
<option value="all">所有产品</option>
<option value="low_stock">低库存产品</option>
<option value="specific">指定产品</option>
</select>
</p>
<p>
<label for="target_channels">目标渠道:</label>
<select name="target_channels[]" id="target_channels" multiple>
<option value="woocommerce">WooCommerce</option>
<option value="taobao">淘宝</option>
<option value="wechat">微信小店</option>
<option value="xiaohongshu">小红书</option>
<option value="douyin">抖音</option>
</select>
</p>
<p>
<input type="submit" name="manual_sync" class="button button-primary" value="执行手动同步">
<input type="submit" name="force_sync" class="button button-secondary" value="强制完全同步">
</p>
</form>
</div>
<div class="sync-settings">
<h2>同步策略设置</h2>
<form method="post" action="options.php">
<?php
settings_fields('culture_stock_sync_options');
do_settings_sections('culture-stock-sync');
?>
<table class="form-table">
<tr>
<th>自动同步频率</th>
<td>
<select name="sync_frequency">
<option value="realtime" <?php selected(get_option('sync_frequency'), 'realtime'); ?>>实时同步</option>
<option value="hourly" <?php selected(get_option('sync_frequency'), 'hourly'); ?>>每小时</option>
<option value="twicedaily" <?php selected(get_option('sync_frequency'), 'twicedaily'); ?>>每12小时</option>
<option value="daily" <?php selected(get_option('sync_frequency'), 'daily'); ?>>每天</option>
</select>
</td>
</tr>
<tr>
<th>低库存预警阈值</th>
<td>
<input type="number" name="low_stock_threshold"
value="<?php echo esc_attr(get_option('low_stock_threshold', 10)); ?>" min="1">
<p class="description">当可用库存低于此值时发送预警通知</p>
</td>
</tr>
<tr>
<th>缓冲库存比例</th>
<td>
<input type="number" name="buffer_percentage"
value="<?php echo esc_attr(get_option('buffer_percentage', 20)); ?>" min="0" max="100">%
<p class="description">为每个渠道保留的缓冲库存比例</p>
</td>
</tr>
<tr>
<th>预售库存处理</th>
<td>
<label>
<input type="checkbox" name="preorder_enabled"
value="1" <?php checked(get_option('preorder_enabled'), 1); ?>>
启用预售库存单独管理
</label>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
</div>
<style>
.stock-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin: 20px 0;
}
.stat-card {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
padding: 20px;
text-align: center;
}
.stat-value {
font-size: 2em;
font-weight: bold;
color: #2271b1;
}
.stat-label {
color: #646970;
margin-top: 5px;
}
</style>
<?php
}
/**
* 显示库存统计
*/
private static function display_stock_statistics() {
global $wpdb;
$stats = $wpdb->get_row("
SELECT
COUNT(DISTINCT product_id) as total_products,
SUM(physical_stock) as total_physical,
SUM(available_stock) as total_available,
SUM(reserved_stock) as total_reserved,
SUM(CASE WHEN available_stock <= min_threshold THEN 1 ELSE 0 END) as low_stock_count
FROM {$wpdb->prefix}culture_stock_main
");
$channels = $wpdb->get_results("
SELECT channel_name, COUNT(*) as product_count, SUM(allocated_stock) as total_allocated
FROM {$wpdb->prefix}culture_stock_channels
GROUP BY channel_name
");
// 显示主要统计
$stat_items = array(
'总产品数' => $stats->total_products,
'物理库存' => $stats->total_physical,
'可用库存' => $stats->total_available,
'预留库存' => $stats->total_reserved,
'低库存产品' => $stats->low_stock_count
);
foreach ($stat_items as $label => $value) {
echo '<div class="stat-card">';
echo '<div class="stat-value">' . esc_html($value) . '</div>';
echo '<div class="stat-label">' . esc_html($label) . '</div>';
echo '</div>';
}
// 显示渠道统计
echo '<div class="stat-card" style="grid-column: span 2;">';
echo '<h3>渠道库存分布</h3>';
foreach ($channels as $channel) {
echo '<p>' . esc_html($channel->channel_name) . ': '
. esc_html($channel->total_allocated) . ' ('
. esc_html($channel->product_count) . '个产品)</p>';
}
echo '</div>';
}
}
?>
## 实时同步与Webhook集成
<?php
/**
- 实时同步与Webhook处理器
*/
class RealTimeSyncHandler {
/**
* 初始化Webhook端点
*/
public static function init_webhooks() {
// 注册REST API端点
add_action('rest_api_init', array(__CLASS__, 'register_rest_endpoints'));
// 设置计划任务
add_action('culture_stock_auto_sync', array(__CLASS__, 'auto_sync_stock'));
if (!wp_next_scheduled('culture_stock_auto_sync')) {
$frequency = get_option('sync_frequency', 'hourly');
wp_schedule_event(time(), $frequency, 'culture_stock_auto_sync');
}
}
/**
* 注册REST API端点
*/
public static function register_rest_endpoints() {
register_rest_route('culture-stock/v1', '/sync', array(
'methods' => 'POST',
'callback' => array(__CLASS__, 'handle_sync_request'),
'permission_callback' => array(__CLASS__, 'verify_webhook_signature'),
'args' => array(
'channel' => array(
'required' => true,
'validate_callback' => function($param) {
return in_array($param, array('taobao', 'wechat', 'douyin', 'xiaohongshu'));
}
),
'product_sku' => array(
'required' => true,
'type' => 'string'
),
'operation' => array(
'required' => true,
'validate_callback' => function($param) {
return in_array($param, array('reduce', 'restore', 'update'));
}
),
'quantity' => array(
'required' => true,
'type' => 'integer',
'sanitize_callback' => 'absint'
),
'timestamp' => array(
'required' => true,
'type' => 'integer'
),
'signature' => array(
'required' => true,
'type' => 'string'
)
)
));
// 库存查询端点
register_rest_route('culture-stock/v1', '/stock/(?P<sku>[a-zA-Z0-9-_]+)', array(
'methods' => 'GET',
'callback' => array(__CLASS__, 'get_stock_info'),
'permission_callback' => '__return_true'
));
}
/**
* 处理同步请求
*/
public static function handle_sync_request(WP_REST_Request $request) {
$channel = $request->get_param('channel');
$sku = $request->get_param('product_sku');
$operation = $request->get_param('operation');
$quantity = $request->get_param('quantity');
// 根据SKU获取产品ID
$product_id = self::get_product_id_by_sku($sku);
if (!$product_id) {
return new WP_REST_Response(array(
'success' => false,
'error' => '产品不存在'
), 404);
}
// 执行库存操作
$stock_sync = new FlexibleStockSync($product_id);
switch ($operation) {
case 'reduce':
$result = $stock_sync->allocate_stock($channel, $quantity);
break;
case 'restore':
$result = self::restore_stock_to_channel($product_id, $channel, $quantity);
break;
case 'update':
$result = self::update_channel_stock($product_id, $channel, $quantity);
break;
default:
$result = array('success' => false, 'error' => '未知操作');
}
// 记录Webhook调用
self::log_webhook_call($channel, $operation, $sku, $quantity, $result['success']);
return new WP_REST_Response($result, $result['success'] ? 200 : 400);
}
/**
* 验证Webhook签名
*/
public static function verify_webhook_signature(WP_REST_Request $request) {
$secret_key = get_option('culture_webhook_secret', '');
if (empty($secret_key)) {
return true; // 未设置密钥时跳过验证
}
$received_signature = $request->get_param('signature');
$timestamp = $request->get_param('timestamp');
// 验证时间戳(防止重放攻击)
$current_time = time();
if (abs($current_time - $timestamp) > 300) { // 5分钟有效期
return false;
}
// 生成预期签名
$data = array(
'channel' => $request->get_param('channel'),
'product_sku' => $request->get_param('product_sku'),
'operation' => $request->get_param('operation'),
'quantity' => $request->get_param('quantity'),
'timestamp' => $timestamp
);
ksort($data);
$signature_string = http_build_query($data);
$expected_signature = hash_hmac('sha256', $signature_string, $secret_key);
return hash_equals($expected_signature, $received_signature);
}
/**
* 自动同步任务
*/
public static function auto_sync_stock() {
global $wpdb;
// 获取需要同步的产品
$products_to_sync = $wpdb->get_results("
SELECT m.product_id, m.available_stock, c.channel_name, c.allocated_stock
FROM {$wpdb->prefix}culture_stock_main m
JOIN {$wpdb->prefix}culture_stock_channels c ON m.id = c.main_stock_id
WHERE m.sync_status = 0
OR TIMESTAMPDIFF(HOUR, m.last_synced, NOW()) >= 1
LIMIT 50
");
foreach ($products_to_sync as $product) {
// 计算库存差异
$diff = $product->available_stock - $product->allocated_stock;
if (abs($diff) > 0) {
// 执行同步
self::sync_single_product($product->product_id, $product->channel_name, $diff);
}
// 更新同步状态
$wpdb->update(
"{$wpdb->prefix}culture_stock_main",
array(
'sync_status' => 1,
'last_synced' => current_time('mysql')
),
array('product_id' => $product->product_id)
);
}
// 检查低库存预警
self::check_low_stock_alerts();
}
/**
* 低库存预警检查
*/
private static function check_low_stock_alerts() {
global $wpdb;
$low_stock_products = $wpdb->get_results("
SELECT m.product_id, m.available_stock, m.min_threshold, p.post_title
FROM {$wpdb->prefix}culture_stock_main m
JOIN {$wpdb->posts} p ON m.product_id = p.ID
WHERE m.available_stock <= m.min_threshold
AND p.post_status = 'publish'
");
if (!empty($low_stock_products)) {
$admin_email = get_option('admin_email');
$subject = '文创产品低库存预警';
$message = "以下产品库存低于预警阈值:nn";
foreach ($low_stock_products as $product) {
$message .= sprintf(
"产品:%sn当前库存:%dn预警阈值:%dnn",
$product->post_title,
$product->available_stock,
$product->min_threshold
);
}
$message .= "请及时处理。n";
$message .= "管理地址:" . admin_url('admin.php?page=culture-stock-sync');
wp_mail($admin_email, $subject, $message);
}
}
}
?>
## 性能优化与缓存策略
<?php
/**
- 库存缓存管理器
*/
class StockCacheManager {
private static $cache_group = 'culture_stock';
private static $cache_expiration = 300; // 5分钟
/**
* 获取带缓存的库存信息
*/
public static function get_cached_stock($product_id, $channel = null) {
$cache_key = self::generate_cache_key($product_id, $channel);
// 尝试从缓存获取
$cached = wp_cache_get($cache_key, self::$cache_group);
if ($cached !== false) {
return $cached;
}
// 缓存未命中,从数据库获取
$stock_data = self::get_stock_from_database($product_id, $channel);
// 存入缓存
wp_cache_set($cache_key, $stock_data, self::$cache_group, self::$cache_expiration);
return $stock_data;
}
/**
* 清除库存缓存
*/
public static function clear_stock_cache($product_id = null, $channel = null) {
if ($product_id) {
// 清除特定产品的所有渠道缓存
$channels = array('woocommerce', 'taobao', 'wechat', 'douyin', 'xiaohongshu', null);
foreach ($channels as $ch) {
$cache_key = self::generate_cache_key($product_id, $ch);
wp_cache_delete($cache_key, self::$cache_group);
}
} else {
// 清除所有缓存
wp_cache_flush_group(self::$cache_group);
}
}
/**
* 批量预加载库存缓存
*/
public static function preload_stock_cache($product_ids) {
global $wpdb;
if (empty($product_ids)) {
return;
}
$ids_placeholder = implode(',', array_fill(0, count($product_ids), '%d'));
$stock_data = $wpdb->get_results($wpdb->prepare("
SELECT m.product_id, c.channel_name, c.allocated_stock, c.buffer_stock
FROM {$wpdb->prefix}culture_stock_main m
LEFT JOIN {$wpdb->prefix}culture_stock_channels c ON m.id = c.main_stock_id
WHERE m.product_id IN ($ids_placeholder)
", $product_ids));
// 组织数据并缓存
$organized_data = array();
foreach ($stock_data as $data) {
$cache_key = self::generate_cache_key($data->product_id, $data->channel_name);
if (!isset($organized_data[$cache_key])) {
$organized_data[$cache_key] = array(
'product_id' => $data->product_id,
'channel' => $data->channel_name,
'allocated' => 0,
'buffer' => 0
);
}
$organized_data[$cache_key]['allocated'] = $data->allocated_stock;
$organized_data[$cache_key]['buffer'] = $data->buffer_stock;
}
foreach ($organized_data as $cache_key => $data) {
wp_cache_set($cache_key, $data, self::$cache_group, self::$cache_expiration);
}
}
/**
* 生成缓存键
*/
private static function generate_cache_key($product_id, $channel) {
return 'stock_' . $product_id . '_' . ($channel ?: 'all');
}
}
/**
- 数据库查询优化
*/
class StockQueryOptimizer {
/**
* 使用索引优化的库存查询
*/
public static function get_optimized_stock_query($product_ids, $channels = null) {
global $wpdb;
$query = "
SELECT
m.product_id,
m.physical_stock,
m.available_stock,
m.reserved_stock,
GROUP_CONCAT(
CONCAT_WS(':', c.channel_name, c.allocated_stock, c.buffer_stock)
SEPARATOR '|'
) as channel_data
FROM {$wpdb->prefix}culture_stock_main m
FORCE INDEX (product_id)
LEFT JOIN {$wpdb->prefix}culture_stock_channels c
ON m.id = c.main_stock_id
AND c.channel_name IN ('woocommerce', 'taobao', 'wechat')
";
if (!empty($product_ids)) {
if (count($product_ids) === 1) {
$query .= $wpdb->prepare
