如何在WooCommerce产品变体中设置特定属性值?
WooCommerce 产品变体属性设置问题
问题描述
我正在开发一款WooCommerce插件,用于从JSON文件导入产品并创建产品变体。目前可变产品的全局属性能正常设置,但单个变体无法绑定特定的属性值——调用$variation->set_attributes($variation_attributes)完全没效果,所有变体都继承了父产品的全部属性选项。请问为单个产品变体定义特定属性值的正确写法是什么?
现有代码
插件核心PHP代码
/** * Plugin Name: WooCommerce JSON Product Importer * Description: Imports WooCommerce products with variations from a JSON file. * Version: 1.0.0 * Author: Joe */ if (!defined('ABSPATH')) { exit; } add_action('admin_menu', 'wcppi_register_menu'); function wcppi_register_menu() { add_menu_page( 'Product JSON Importer', 'Product Importer', 'manage_options', 'wcppi-importer', 'wcppi_importer_page', 'dashicons-upload', 20 ); } function wcppi_importer_page() { ?> <div class="wrap"> <h1>WooCommerce Product Importer</h1> <form method="post" enctype="multipart/form-data"> <input type="file" name="product_json" required><br><br> <input type="submit" name="import_submit" value="Import Products"> </form> </div> <?php if (isset($_POST['import_submit'])) { wcppi_handle_import(); } } function wcppi_handle_import() { if (isset($_FILES['product_json'])) { $json_file = $_FILES['product_json']['tmp_name']; $json_data = file_get_contents($json_file); $products = json_decode($json_data, true); if (!$products) { echo '<p>Error: Invalid JSON format.</p>'; return; } $array = [ 'pa_color' => array('Blue', 'Red', 'Green'), 'pa_size' => array('S', 'M','L'), ]; foreach($array as $attribute_slug => $terms){ if (!taxonomy_exists($attribute_slug)) { $attribute_id[$attribute_slug] = wc_create_attribute(array( 'name' => ucfirst(str_replace('pa_', '', $attribute_slug)), 'slug' => $attribute_slug, // Attribute slug 'type' => 'select', // Type (dropdown) 'order_by' => 'menu_order', // Order by menu order 'has_archives' => false, )); // Register the taxonomy for the attribute register_taxonomy($attribute_slug, 'product', array( 'label' => ucfirst(str_replace('pa_', '', $attribute_slug)), 'public' => true, 'hierarchical' => false, 'show_ui' => false, 'query_var' => true, 'rewrite' => false, )); } } foreach ($array as $attribute_slug => $terms) { foreach ($terms as $term) { if (!term_exists($term, $attribute_slug)) { wp_insert_term($term, $attribute_slug); } } } foreach ($products as $product_data) { wcppi_import_product($product_data); } echo '<p>Products imported successfully!</p>'; } } function wcppi_import_product($data) { $product = new WC_Product_Variable(); $product->set_name($data['name']); $product->set_description($data['description']); $product->set_sku($data['sku']); $product->set_status('publish'); $product->save(); $product_id = $product->get_id(); $attributes = array(); // Initializing $position = $attr_id = 0; // Initializing foreach ($data['attributes'] as $taxonomy => $terms ) { $attr_id++; $attribute = new WC_Product_Attribute(); $attribute->set_id($attr_id); $attribute->set_name("pa_" . lcfirst($taxonomy)); $attribute->set_position($position); $attribute->set_visible(1); $attribute->set_variation(1); $attributes["pa_" . lcfirst($taxonomy)] = $attribute; $position++; } $product->set_attributes($attributes); $product_id = $product->save(); // Save product that returns the product ID foreach ($data['attributes'] as $taxonomy => $terms ) { wp_set_object_terms( $product_id, $terms, "pa_" . lcfirst($taxonomy), true ); } foreach ($data['variations'] as $variation_data) { wcppi_import_variation($product_id, $variation_data); } } function wcppi_import_variation($product_id, $data) { $variation = new WC_Product_Variation(); $variation->set_parent_id($product_id); $variation->set_regular_price($data['price']); $variation->set_sku($data['sku']); $variation_attributes = []; foreach ($data['attributes'] as $attribute_name => $attribute_value) { $taxonomy = 'pa_' . lcfirst($attribute_name); $variation_attributes[$taxonomy] = $attribute_value; } $variation->set_attributes($variation_attributes); $product_id = $variation->save(); foreach ($data['attributes'] as $taxonomy => $terms ) { wp_set_object_terms( $product_id, $terms, "pa_" . lcfirst($taxonomy), true ); } }
导入用的JSON文件
[ { "name": "T-shirt", "sku": "TSHIRT001", "description": "A stylish t-shirt", "attributes": { "Color": ["Red", "Blue", "Green"], "Size": ["S", "M", "L"] }, "variations": [ { "sku": "TSHIRT001-RED-S", "price": "19.99", "attributes": { "Color": "Red", "Size": "S" } }, { "sku": "TSHIRT001-RED-M", "price": "19.99", "attributes": { "Color": "Red", "Size": "M" } }, { "sku": "TSHIRT001-BLUE-S", "price": "19.99", "attributes": { "Color": "Blue", "Size": "S" } } ] }, { "name": "Hoodie", "sku": "HOODIE001", "description": "A warm hoodie", "attributes": { "Color": ["Black", "White"], "Size": ["M", "L", "XL"] }, "variations": [ { "sku": "HOODIE001-BLACK-M", "price": "29.99", "attributes": { "Color": "Black", "Size": "M" } }, { "sku": "HOODIE001-BLACK-L", "price": "29.99", "attributes": { "Color": "Black", "Size": "L" } }, { "sku": "HOODIE001-WHITE-XL", "price": "29.99", "attributes": { "Color": "White", "Size": "XL" } } ] } ]
问题原因及修正方案
核心问题点
- 变体属性值用了名称而非Slug:WooCommerce变体的属性值需要存储对应术语的slug(小写、空格转横杠),而不是显示名称。
- 多余的
wp_set_object_terms调用:在wcppi_import_variation函数中,错误地给变体设置了所有属性术语,覆盖了之前用set_attributes设置的特定值。 - 父产品属性未关联术语:原代码中创建
WC_Product_Attribute时没有设置术语列表,导致父产品属性不完整。
修正后的关键函数代码
修正wcppi_import_product函数
function wcppi_import_product($data) { $product = new WC_Product_Variable(); $product->set_name($data['name']); $product->set_description($data['description']); $product->set_sku($data['sku']); $product->set_status('publish'); $attributes = array(); $position = 0; foreach ($data['attributes'] as $taxonomy_name => $term_names ) { $taxonomy = 'pa_' . lcfirst($taxonomy_name); // 获取术语的slug列表 $term_slugs = array(); foreach ($term_names as $term_name) { $term = get_term_by('name', $term_name, $taxonomy); if ($term) { $term_slugs[] = $term->slug; } } $attribute = new WC_Product_Attribute(); // 不需要手动设置ID,保存时会自动生成 $attribute->set_name($taxonomy); $attribute->set_position($position); $attribute->set_visible(1); $attribute->set_variation(1); $attribute->set_options($term_slugs); // 关联术语slug $attributes[] = $attribute; $position++; } $product->set_attributes($attributes); $product_id = $product->save(); foreach ($data['attributes'] as $taxonomy_name => $term_names ) { $taxonomy = 'pa_' . lcfirst($taxonomy_name); wp_set_object_terms( $product_id, $term_names, $taxonomy, true ); } foreach ($data['variations'] as $variation_data) { wcppi_import_variation($product_id, $variation_data); } }
修正wcppi_import_variation函数
function wcppi_import_variation($product_id, $data) { $variation = new WC_Product_Variation(); $variation->set_parent_id($product_id); $variation->set_regular_price($data['price']); $variation->set_sku($data['sku']); $variation_attributes = []; foreach ($data['attributes'] as $attribute_name => $attribute_value) { $taxonomy = 'pa_' . lcfirst($attribute_name); // 获取术语的slug $term = get_term_by('name', $attribute_value, $taxonomy); if ($term) { $variation_attributes[$taxonomy] = $term->slug; } else { // 如果术语不存在,用名称降级处理(不推荐,最好提前创建) $variation_attributes[$taxonomy] = sanitize_title($attribute_value); } } $variation->set_attributes($variation_attributes); $variation->save(); // 移除多余的wp_set_object_terms调用,避免覆盖属性值 }
额外优化点
- 原
wcppi_handle_import中硬编码的属性列表可以移除,直接从JSON数据中动态创建属性和术语,避免重复或遗漏。 - 添加错误处理,比如术语不存在时的提示,确保导入稳定性。
内容的提问来源于stack exchange,提问作者zony
相关产品推荐
相关产品推荐

