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

从Printify导入WooCommerce时变体价格未同步问题及代码优化需求

解决Printify导入WooCommerce时的变体价格同步问题

问题说明

将商品从Printify服务导入WooCommerce平台时,已通过代码将自定义颜色、尺寸属性转换为全局属性,但变体价格未同步Printify数据,导致价格属性缺失或不匹配。以下是修复后的完整代码,新增价格同步功能并修正原代码逻辑问题。

修改后的完整代码

add_action('rest_after_insert_product', function($product) {
    $product_id = $product->get_id();
    error_log("正在处理商品: $product_id");
    
    convert_custom_to_global_attributes($product_id);
    update_variation_prices($product_id);
}, 10, 1);

add_action('shutdown', function() {
    global $wpdb;
    $products = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish'");
    foreach ($products as $product_id) {
        convert_custom_to_global_attributes($product_id);
    }
});

add_action('woocommerce_before_single_product', function() {
    $product = wc_get_product(get_the_ID());
    $attributes = $product->get_attributes();
    error_log("商品属性: " . print_r($attributes, true));
});

/**
 * 将自定义属性转换为全局属性
 */
function convert_custom_to_global_attributes($product_id) {
    $product = wc_get_product($product_id);

    if (!$product) {
        error_log("未找到商品: $product_id");
        return;
    }

    $attributes = $product->get_attributes();
    $updated_attributes = []; // 仅存储全局属性
    $attribute_mapping = [
        'custom_sizes' => 'pa_sizes',
        'custom_colors' => 'pa_colors',
    ];
    
    foreach ($attributes as $key => $attr) {
        if (!$attr->is_taxonomy()) { // 检查是否为自定义属性
            $name = $attr->get_name();
            $taxonomy = 'pa_' . sanitize_title($name);

            // 如果全局属性不存在则创建
            if (!taxonomy_exists($taxonomy)) {
                $result = wc_create_attribute([
                    'name'         => $name,
                    'slug'         => sanitize_title($name),
                    'type'         => 'select',
                    'order_by'     => 'menu_order',
                    'has_archives' => false,
                ]);

                if (is_wp_error($result)) {
                    error_log("创建全局属性 $name 失败: " . $result->get_error_message());
                    continue;
                }

                register_taxonomy($taxonomy, 'product', [
                    'hierarchical' => true,
                    'show_ui'      => false,
                    'query_var'    => true,
                    'rewrite'      => false,
                ]);
            }

            // 将自定义属性值转换为全局分类术语
            $options = $attr->get_options();
            foreach ($options as $option) {
                if (!term_exists($option, $taxonomy)) {
                    $term_result = wp_insert_term($option, $taxonomy);

                    if (is_wp_error($term_result)) {
                        error_log("在分类 '$taxonomy' 中创建术语 '$option' 失败: " . $term_result->get_error_message());
                    } else {
                        error_log("已在分类 '$taxonomy' 中创建术语 '$option'。");
                    }
                }
            }

            // 准备全局属性对象
            $global_attribute = new WC_Product_Attribute();
            $global_attribute->set_id(wc_attribute_taxonomy_id_by_name($name));
            $global_attribute->set_name($taxonomy);
            $global_attribute->set_options($options);
            $global_attribute->set_visible($attr->get_visible());
            $global_attribute->set_variation($attr->get_variation());

            $updated_attributes[$taxonomy] = $global_attribute; // 添加到更新后的属性列表
            $attribute_mapping[$name] = $taxonomy; // 映射旧属性名到全局分类
        } else {
            // 保留已存在的全局属性
            $updated_attributes[$key] = $attr;
        }
    }

    // 更新商品,仅保留全局属性
    $product->set_attributes($updated_attributes);
    $product->save();
    
    // 更新变体以使用全局属性
    update_variation_attributes($product_id, $attribute_mapping);
}

/**
 * 更新变体的属性映射
 */
function update_variation_attributes($product_id, $attribute_mapping) {
    $product = wc_get_product($product_id);

    if (!$product || !$product->is_type('variable')) {
        error_log("商品 $product_id 不是可变商品或未找到。");
        return;
    }

    $variations = $product->get_children();
    $used_sizes = [];
    $used_colors = [];

    foreach ($variations as $variation_index => $variation_id) {
        $variation = wc_get_product($variation_id);

        if (!$variation) {
            error_log("未找到商品 $product_id 的变体 $variation_id。");
            continue;
        }

        $updated_attributes = [];
        $missing_attributes = [];
        $current_attributes = $variation->get_attributes();

        foreach ($attribute_mapping as $custom_name => $global_taxonomy) {
            $custom_value = $variation->get_attribute($custom_name);

            if ($custom_value) {
                $term = get_term_by('name', $custom_value, $global_taxonomy);
                if ($term) {
                    // 检查当前变体是否已设置正确的全局属性
                    if (!isset($current_attributes['attribute_' . $global_taxonomy]) || $current_attributes['attribute_' . $global_taxonomy] !== $term->slug) {
                        $updated_attributes['attribute_' . $global_taxonomy] = $term->slug;
                        error_log("变体 $variation_id: 将 '$custom_name' 映射到全局分类 '$global_taxonomy' 的术语 '{$term->slug}'。");
                    }

                    // 记录已使用的属性值
                    if ($global_taxonomy === 'pa_sizes') {
                        $used_sizes[] = $term->slug;
                    }
                    if ($global_taxonomy === 'pa_colors') {
                        $used_colors[] = $term->slug;
                    }
                } else {
                    $missing_attributes[] = $global_taxonomy;
                    error_log("变体 $variation_id: 在分类 '$global_taxonomy' 中未找到术语 '$custom_value'。");
                }
            } else {
                // 如果属性值缺失,自动分配可用术语
                $attribute_terms = get_terms([
                    'taxonomy' => $global_taxonomy,
                    'hide_empty' => false,
                ]);

                if (!empty($attribute_terms)) {
                    $term_slug = $attribute_terms[$variation_index % count($attribute_terms)]->slug;

                    // 避免重复分配术语
                    if (
                        ($global_taxonomy === 'pa_sizes' && !in_array($term_slug, $used_sizes)) ||
                        ($global_taxonomy === 'pa_colors' && !in_array($term_slug, $used_colors))
                    ) {
                        $updated_attributes['attribute_' . $global_taxonomy] = $term_slug;
                        error_log("变体 $variation_id: 为 '$global_taxonomy' 分配术语 '{$term_slug}'。");
                    }
                } else {
                    $missing_attributes[] = $global_taxonomy;
                    error_log("变体 $variation_id: 分类 '$global_taxonomy' 下无可用术语。");
                }
            }
        }

        if (!empty($updated_attributes)) {
            // 设置新属性并保存变体
            $variation->set_attributes(array_merge($current_attributes, $updated_attributes));
            $variation->save();
            
        } else {
            error_log("商品 $product_id 的变体 $variation_id 未更新任何属性。缺失属性: " . implode(', ', $missing_attributes));
        }
    }

    // 同步可变商品数据
    WC_Product_Variable::sync($product_id);
    wc_delete_product_transients($product_id);
}

/**
 * 同步变体的Printify价格
 */
function update_variation_prices($product_id) {
    $product = wc_get_product($product_id);

    if (!$product || !$product->is_type('variable')) {
        error_log("商品 $product_id 不是可变商品或未找到,跳过价格同步。");
        return;
    }

    $variations = $product->get_children();

    foreach ($variations as $variation_id) {
        $variation = wc_get_product($variation_id);

        if (!$variation) {
            error_log("未找到商品 $product_id 的变体 $variation_id,跳过价格同步。");
            continue;
        }

        // 从Printify元数据获取价格(根据实际元键调整)
        $printify_regular_price = get_post_meta($variation_id, '_printify_regular_price', true);
        $printify_sale_price = get_post_meta($variation_id, '_printify_sale_price', true);

        // 更新常规价格
        if (!empty($printify_regular_price)) {
            $variation->set_regular_price($printify_regular_price);
            error_log("变体 $variation_id: 同步常规价格为 $printify_regular_price");
        }

        // 更新促销价格(如果存在)
        if (!empty($printify_sale_price)) {
            $variation->set_sale_price($printify_sale_price);
            error_log("变体 $variation_id: 同步促销价格为 $printify_sale_price");
        }

        // 保存变体价格
        $variation->save();
    }

    // 清除商品缓存
    wc_delete_product_transients($product_id);
}

关键修改说明

  • 新增update_variation_prices函数:从Printify存储的元数据中提取变体价格,同步到WooCommerce的常规价格和促销价格字段
  • 修正原代码中重复覆盖attribute_mapping的逻辑错误
  • 移除原代码中未定义变量的错误日志输出
  • 确保变体在完成属性转换后自动触发价格同步

内容的提问来源于stack exchange,提问作者Юрий Ришко

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 17:26:08