php 以编程方式创建具有新属性值的 WooCommerce 产品变体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47518280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:34:10  来源:igfitidea点击:

Create programmatically a WooCommerce product variation with new attribute values

phpwordpresswoocommerceproductvariations

提问by Cedric

I have created a variable product ("parent" product) in WooCommerce version 3+. From a WordPress plugin, I would like to programmatically create the product variations ("children" product) with new attribute values.

我在 WooCommerce 版本 3+ 中创建了一个可变产品(“父”产品)。从 WordPress 插件,我想以编程方式创建具有新属性值的产品变体(“儿童”产品)。

The variation attributes are already set in WooCommerce.
So every time one variation is created, the new attribute's values should be created programmatically too and set in the parent Variable product.

WooCommerce 中已经设置了变体属性。
因此,每次创建一个变体时,新属性的值也应该以编程方式创建并设置在父变量产品中。

How can this be done? is it possible?

如何才能做到这一点?是否可以?



Update : I had written more lines of codes on this that I wished, and tried many things to solve it, using woocommerce objects, and added missing data about terms, termmeta, the relationship from term with post, in the database using the WordPress database object - but nothing has sufficed to make it work. And I couldn't pin-point where I went wrong - that is why I couldn't provide a narrower problem - things for which stackoverflow is more made for.

更新:我已经写了更多我希望的代码行,并尝试了很多方法来解决它,使用 woocommerce 对象,并使用 WordPress 数据库在数据库中添加了有关术语、termmeta、术语与帖子的关系的缺失数据对象 - 但没有什么足以使它工作。而且我无法指出我出错的地方——这就是为什么我不能提供一个更窄的问题——stackoverflow 更适合做的事情。

回答by LoicTheAztec

Update January 2020:Changed to WC_Productmethod get_name()instead of get_title()
Update September 2018:Handling taxonomy creation (Thanks to Carl F. Corneil)

2020 年 1 月更新:更改为WC_Product方法get_name()而不是get_title()
2018 年 9 月更新:处理分类法创建(感谢 Carl F. Corneil)

From a defined variable product ID You will find bellow, a custom function that will add (create) a Product variation. The variable parent product needs to have set for it the needed attributes.

从定义的变量产品 ID 您将在下面找到一个自定义函数,该函数将添加(创建)产品变体。变量父产品需要为其设置所需的属性。

You will need to provide some information as:

您需要提供以下信息:

  • the array of attributes/values
  • the Sku, prices and stock….
  • 属性/值数组
  • Sku、价格和库存……

This data has to be stored in a formatted multi dimensional array (see an example at the end).

此数据必须存储在格式化的多维数组中(请参阅最后的示例)

This function will check if the attributes values (term name) already exist and if not: - it create it for the product attribute - set it in the parent variable product.

该函数将检查属性值(术语名称)是否已经存在,如果不存在: - 它为产品属性创建它 - 在父变量 product 中设置它。

The custom function code:

自定义函数代码:

/**
 * Create a product variation for a defined variable product ID.
 *
 * @since 3.0.0
 * @param int   $product_id |?Post ID of the product parent variable product.
 * @param array $variation_data | The data to insert in the product.
 */

function create_product_variation( $product_id, $variation_data ){
    // Get the Variable product object (parent)
    $product = wc_get_product($product_id);

    $variation_post = array(
        'post_title'  => $product->get_name(),
        'post_name'   => 'product-'.$product_id.'-variation',
        'post_status' => 'publish',
        'post_parent' => $product_id,
        'post_type'   => 'product_variation',
        'guid'        => $product->get_permalink()
    );

    // Creating the product variation
    $variation_id = wp_insert_post( $variation_post );

    // Get an instance of the WC_Product_Variation object
    $variation = new WC_Product_Variation( $variation_id );

    // Iterating through the variations attributes
    foreach ($variation_data['attributes'] as $attribute => $term_name )
    {
        $taxonomy = 'pa_'.$attribute; // The attribute taxonomy

        // If taxonomy doesn't exists we create it (Thanks to Carl F. Corneil)
        if( ! taxonomy_exists( $taxonomy ) ){
            register_taxonomy(
                $taxonomy,
               'product_variation',
                array(
                    'hierarchical' => false,
                    'label' => ucfirst( $attribute ),
                    'query_var' => true,
                    'rewrite' => array( 'slug' => sanitize_title($attribute) ), // The base slug
                ),
            );
        }

        // Check if the Term name exist and if not we create it.
        if( ! term_exists( $term_name, $taxonomy ) )
            wp_insert_term( $term_name, $taxonomy ); // Create the term

        $term_slug = get_term_by('name', $term_name, $taxonomy )->slug; // Get the term slug

        // Get the post Terms names from the parent variable product.
        $post_term_names =  wp_get_post_terms( $product_id, $taxonomy, array('fields' => 'names') );

        // Check if the post term exist and if not we set it in the parent variable product.
        if( ! in_array( $term_name, $post_term_names ) )
            wp_set_post_terms( $product_id, $term_name, $taxonomy, true );

        // Set/save the attribute data in the product variation
        update_post_meta( $variation_id, 'attribute_'.$taxonomy, $term_slug );
    }

    ## Set/save all other data

    // SKU
    if( ! empty( $variation_data['sku'] ) )
        $variation->set_sku( $variation_data['sku'] );

    // Prices
    if( empty( $variation_data['sale_price'] ) ){
        $variation->set_price( $variation_data['regular_price'] );
    } else {
        $variation->set_price( $variation_data['sale_price'] );
        $variation->set_sale_price( $variation_data['sale_price'] );
    }
    $variation->set_regular_price( $variation_data['regular_price'] );

    // Stock
    if( ! empty($variation_data['stock_qty']) ){
        $variation->set_stock_quantity( $variation_data['stock_qty'] );
        $variation->set_manage_stock(true);
        $variation->set_stock_status('');
    } else {
        $variation->set_manage_stock(false);
    }

    $variation->set_weight(''); // weight (reseting)

    $variation->save(); // Save the data
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

代码位于活动子主题(或主题)的 function.php 文件或任何插件文件中。

Usage (example with 2 attributes):

用法(具有 2 个属性的示例):

$parent_id = 746; // Or get the variable product id dynamically

// The variation data
$variation_data =  array(
    'attributes' => array(
        'size'  => 'M',
        'color' => 'Green',
    ),
    'sku'           => '',
    'regular_price' => '22.00',
    'sale_price'    => '',
    'stock_qty'     => 10,
);

// The function to be run
create_product_variation( $parent_id, $variation_data );

Tested and works.

测试和工作。

Part 2:Create programmatically a variable product and two new attributes in WooCommerce

第 2 部分:在 WooCommerce 中以编程方式创建可变产品和两个新属性

You will get this in backend:

你会在后端得到这个:

enter image description here

enter image description here

And it will work perfectly in front end.

它将在前端完美运行。

Related:Create programmatically a product using CRUD methods in Woocommerce 3

相关:在 Woocommerce 3 中使用 CRUD 方法以编程方式创建产品

回答by PKSWE

I'm just going to throw this out there, since i couldn't get any of the above examples working. Don't ask me why as other people seem to have success. So, i took the minimalist approach and tried to figure out the bare essentials for a product attribute + variation (by creating it manually in wp and looking at the db) and came up with this.

我只是想把它扔在那里,因为我无法让上面的任何例子工作。不要问我为什么,因为其他人似乎取得了成功。所以,我采用了极简主义的方法,并试图找出产品属性 + 变体的基本要素(通过在 wp 中手动创建并查看数据库)并提出了这个。

$article_name = 'Test';

$post_id = wp_insert_post( array(
    'post_author' => 1,
    'post_title' => $article_name,
    'post_content' => 'Lorem ipsum',
    'post_status' => 'publish',
    'post_type' => "product",
) );
wp_set_object_terms( $post_id, 'variable', 'product_type' );

$attr_label = 'Test attribute';
$attr_slug = sanitize_title($attr_label);

$attributes_array[$attr_slug] = array(
    'name' => $attr_label,
    'value' => 'alternative 1 | alternative 2',
    'is_visible' => '1',
    'is_variation' => '1',
    'is_taxonomy' => '0' // for some reason, this is really important       
);
update_post_meta( $post_id, '_product_attributes', $attributes_array );

$parent_id = $post_id;
$variation = array(
    'post_title'   => $article_name . ' (variation)',
    'post_content' => '',
    'post_status'  => 'publish',
    'post_parent'  => $parent_id,
    'post_type'    => 'product_variation'
);

$variation_id = wp_insert_post( $variation );
update_post_meta( $variation_id, '_regular_price', 2 );
update_post_meta( $variation_id, '_price', 2 );
update_post_meta( $variation_id, '_stock_qty', 10 );
update_post_meta( $variation_id, 'attribute_' . $attr_slug, 'alternative 1' );
WC_Product_Variable::sync( $parent_id );

$variation_id = wp_insert_post( $variation );
update_post_meta( $variation_id, '_regular_price', 2 );
update_post_meta( $variation_id, '_price', 2 );
update_post_meta( $variation_id, '_stock_qty', 10 );
update_post_meta( $variation_id, 'attribute_' . $attr_slug, 'alternative 2' );
WC_Product_Variable::sync( $parent_id );

This is not using global product attributes, but article specific ones. Hope it helps someone as i was about ready to tear my hair out before i got it working.

这不是使用全局产品属性,而是使用特定于文章的属性。希望它可以帮助某人,因为我正准备在我开始工作之前将头发撕掉。

回答by Davey

Expanding on LoicTheAztec's answer, you can check if the attribute combination exists with the following modification to his code.

扩展 LoicTheAztec 的答案,您可以通过对他的代码进行以下修改来检查属性组合是否存在。

function create_update_product_variation( $product_id, $variation_data ){

    if(isset($variation_data['variation_id'])) {

      $variation_id = $variation_data['variation_id'];

    } else {

      // if the variation doesn't exist then create it

      // Get the Variable product object (parent)
      $product = wc_get_product($product_id);

      $variation_post = array(
          'post_title'  => $product->get_title(),
          'post_name'   => 'product-'.$product_id.'-variation',
          'post_status' => 'publish',
          'post_parent' => $product_id,
          'post_type'   => 'product_variation',
          'guid'        => $product->get_permalink()
      );

      // Creating the product variation
      $variation_id = wp_insert_post( $variation_post );

    }

    // ...

}

Example usage

示例用法

// The variation data
$variation_data =  array(
    'attributes' => array(
        'size'  => 'M',
        'color' => 'Green',
    ),
    'sku'           => '',
    'regular_price' => '22.00',
    'sale_price'    => '1',
    'stock_qty'     => 1,
);

// check if variation exists
$meta_query = array();
foreach ($variation_data['attributes'] as $key => $value) {
  $meta_query[] = array(
    'key' => 'attribute_pa_' . $key,
    'value' => $value
  );
}

$variation_post = get_posts(array(
  'post_type' => 'product_variation',
  'numberposts' => 1,
  'post_parent'   => $parent_id,
  'meta_query' =>  $meta_query
));

if($variation_post) {
  $variation_data['variation_id'] = $variation_post[0]->ID;
}

create_update_product_variation( $product_id, $variation_data );

回答by Carl F. Corneil

You might run into a problem here if the the taxonomy of the product is not registered beforehand somewhere else. If you want to make sure the taxonomy exists, you could add a conditional to LoicTheAztec's answer.

如果产品的分类没有事先在其他地方注册,您可能会在这里遇到问题。如果您想确保分类法存在,您可以在 LoicTheAztec 的答案中添加一个条件。

Something like this.

像这样的东西。

foreach ($variation_data['attributes'] as $attribute => $term_name )
{
    //echo 'attribute ' . $attribute . ' term name ' . $term_name;

    $taxonomy = 'pa_' . $attribute; // The attribute taxonomy

    // Check if the Taxonomy exists, and if not we create it.

    if (! taxonomy_exists($taxonomy)){
        register_taxonomy(  
            $taxonomy,  //The name of the taxonomy. Name should be in slug form (must not contain capital letters or spaces). 
            'product',        //post type name
            array(  
                'hierarchical' => false,  
                'label' => ucfirst($taxonomy),  //Display name
                'query_var' => true,
                'rewrite' => array(
                    'slug' => $taxonomy, // This controls the base slug that will display before each term
                    'with_front' => false // Don't display the category base before 
                ),
            )  
        ); 

    }
...

回答by Lucas Bustamante

If you want to generate products for testing in WooCommerce, you can use WooCommerce Smooth Generator, made by WooCommerce itself.

如果您想在 WooCommerce 中生成用于测试的产品,您可以使用WooCommerce 自己制作的 WooCommerce Smooth Generator

https://github.com/woocommerce/wc-smooth-generator

https://github.com/woocommerce/wc-smooth-generator

Example:

例子:

// Generate WC_Product object and save it to database
// 70% change generated product is simple
// 30% chance generated product is variable
$product = \WC\SmoothGenerator\Generator\Product::generate();

// Returns WC_Product object of Simple product and don't save it  to database
$product = \WC\SmoothGenerator\Generator\Product::generate_simple_product();

// Returns WC_Product object of Variable Product and saves it to database
$variable_product = \WC\SmoothGenerator\Generator\Product::generate_variable_product();

Src: https://github.com/woocommerce/wc-smooth-generator/blob/master/includes/Generator/Product.php

源代码:https: //github.com/woocommerce/wc-smooth-generator/blob/master/includes/Generator/Product.php

If you want to create products programatically, you can Product class with your needs.

如果您想以编程方式创建产品,您可以根据您的需要进行 Product 类。

回答by Orlando J. Depablos Morales

it works but needs a little corrections (2 commas in the fuctions array), I did edit some of the code to my needs.

它有效但需要一些更正(函数数组中的 2 个逗号),我确实根据需要编辑了一些代码。

(working on wp 4.9 | wc 3.5)

(在 wp 4.9 | wc 3.5 上工作)

First the products needs to have the attribute already created and associated, my taxonomy is "pa_r" friendly name "R" backend attribute associeated img

首先产品需要有已经创建和关联的属性,我的分类是“pa_r”友好名称“R” 后端属性关联img

the function with the correction

带校正功能

function create_product_variation( $product_id, $variation_data ){
// Get the Variable product object (parent)
$product = wc_get_product($product_id);

$variation_post = array(
    'post_title'  => $product->get_title(),
    'post_name'   => 'product-'.$product_id.'-variation',
    'post_status' => 'publish',
    'post_parent' => $product_id,
    'post_type'   => 'product_variation',
    'guid'        => $product->get_permalink()
);

// Creating the product variation
$variation_id = wp_insert_post( $variation_post );

// Get an instance of the WC_Product_Variation object
$variation = new WC_Product_Variation( $variation_id );

// Iterating through the variations attributes
foreach ($variation_data['attributes'] as $attribute => $term_name )
{
    $taxonomy = 'pa_'.$attribute; // The attribute taxonomy

    // If taxonomy doesn't exists we create it (Thanks to Carl F. Corneil)
    if( ! taxonomy_exists( $taxonomy ) ){
        register_taxonomy(
            $taxonomy,
            'product_variation',
            array(
                'hierarchical' => false,
                'label' => ucfirst( $taxonomy ),
                'query_var' => true,
                'rewrite' => array( 'slug' => '$taxonomy') // The base slug
            )
        );
    }

    // Check if the Term name exist and if not we create it.
    if( ! term_exists( $term_name, $taxonomy ) )
        wp_insert_term( $term_name, $taxonomy ); // Create the term

    $term_slug = get_term_by('name', $term_name, $taxonomy )->slug; // Get the term slug

    // Get the post Terms names from the parent variable product.
    $post_term_names =  wp_get_post_terms( $product_id, $taxonomy, array('fields' => 'names') );

    // Check if the post term exist and if not we set it in the parent variable product.
    if( ! in_array( $term_name, $post_term_names ) )
        wp_set_post_terms( $product_id, $term_name, $taxonomy, true );

    // Set/save the attribute data in the product variation
    update_post_meta( $variation_id, 'attribute_'.$taxonomy, $term_slug );
}

## Set/save all other data

// SKU
if( ! empty( $variation_data['sku'] ) )
    $variation->set_sku( $variation_data['sku'] );

// Prices
if( empty( $variation_data['sale_price'] ) ){
    $variation->set_price( $variation_data['regular_price'] );
} else {
    $variation->set_price( $variation_data['sale_price'] );
    $variation->set_sale_price( $variation_data['sale_price'] );
}
$variation->set_regular_price( $variation_data['regular_price'] );

// Stock
if( ! empty($variation_data['stock_qty']) ){
    $variation->set_stock_quantity( $variation_data['stock_qty'] );
    $variation->set_manage_stock(true);
    $variation->set_stock_status('');
} else {
    $variation->set_manage_stock(false);
}

$variation->set_weight(''); // weight (reseting)

$variation->save(); // Save the data
}

I made an array with the data I need in the variations [id_post, attribute, sku, regular_price, stock]

我用我需要的数据制作了一个数组 [id_post, attribute, sku, regular_price, stock]

$hijos = array(
[9623,'265/70 R16','NE-CT-CO-USA-016-005','0',53],
[9624,'235/65 R17','NE-AU-CO-EUR-017-050','189000',56]
);

and the foreach to create dynamically all the variations to my products

和 foreach 动态创建我的产品的所有变体

foreach ($hijos as $vari) {
// The variation data
$variation_data =  array(
    'attributes' => array(
        'r'  => $vari[1],
    ),
    'sku'           => $vari[2],
    'regular_price' => str_replace('.', '', $vari[3]),
    'stock_qty'     => $vari[4]
);
// var_dump($variation_data);
create_product_variation( $vari[0], $variation_data );
}

回答by Syed Muhammad Shafiq

above answer (LoicTheAztec) helped me a lot but there was some issues instead of using

以上答案(LoicTheAztec)对我帮助很大,但有一些问题而不是使用

update_post_meta( $variation_id, 'attribute_'.$taxonomy, $term_slug );

update_post_meta( $variation_id, 'attribute_'.$taxonomy, $term_slug );

use :
update_post_meta( $variation_id, 'attribute_'.$attribute, $term_name );

用 :
update_post_meta( $variation_id, 'attribute_'.$attribute, $term_name );

because taxonomy is already is been modified and this is causing problem to update post meta after changing this update values and not selecting automatically in admin product variation edit after this changes it work great !

因为分类法已经被修改,这会导致在更改此更新值后更新 post meta 出现问题,并且在此更改后不会在管理产品变体编辑中自动选择它工作得很好!