WooCommerce:按代码创建产品

时间:2012-07-16 11:49:10

标签: php wordpress woocommerce

我的商店出售乙烯基贴纸。每个产品(贴纸)有144种不同(24种颜色,3种尺寸和2种方向)。每个变体都是分配唯一SKU所必需的。

手动填充目录是不现实的。我将创建一个表单,用户可以在其中指定产品的名称,描述和主要图像,以及可能的大小和颜色。在处理表单时,我需要创建一个产品及其所有变体。

如何创建产品及其变体?

5 个答案:

答案 0 :(得分:13)

As Jason wrote in his comment, REST API is the way to go here. This can be done even without HTTP REST requests, making it work even on Wordpress installations that have their REST interface disabled.

Here is a simple function that I made for this purpose:

$products_controler = new WC_REST_Products_Controller();
function create_item($rest_request) {
    global $products_controler;
    if (!isset($rest_request['status']))
        $rest_request['status'] = 'publish';
    $wp_rest_request = new WP_REST_Request('POST');
    $wp_rest_request->set_body_params($rest_request);
    return $products_controler->create_item($wp_rest_request);
}

Here, $rest_request is an array that you'd usually send via REST (see the docs here).

The $products_controler variable is global because I needed to call this function multiple times and I didn't want to recreate the object each time. Feel free to make it local.

This works for all types of products (simple, grouped, variable,...) and it should be more resistant to internal changes of WooCommerce than adding the products manually through wp_insert_post and update_post_meta.

Edit: Given that this answer still get an occasional upvote, here is a WooCommerce 3.0+ update. The change is that the variations no longer get added automatically, so we have to do it by ourselves.

This is the current version of the function:

protected function create_item( $rest_request ) {
    if ( ! isset( $rest_request['status'] ) ) {
        $rest_request['status'] = $this->plugin->get_option( 'default_published_status' );
    }
    if ( ! isset( $this->products_controler ) ) {
        $this->products_controler = new WC_REST_Products_Controller();
    }
    $wp_rest_request = new WP_REST_Request( 'POST' );
    $wp_rest_request->set_body_params( $rest_request );
    $res = $this->products_controler->create_item( $wp_rest_request );
    $res = $res->data;
    // The created product must have variations
    // If it doesn't, it's the new WC3+ API which forces us to build those manually
    if ( ! isset( $res['variations'] ) )
        $res['variations'] = array();
    if ( count( $res['variations'] ) == 0 && count( $rest_request['variations'] ) > 0 ) {
        if ( ! isset( $this->variations_controler ) ) {
            $this->variations_controler = new WC_REST_Product_Variations_Controller();
        }
        foreach ( $rest_request['variations'] as $variation ) {
            $wp_rest_request = new WP_REST_Request( 'POST' );
            $variation_rest = array(
                'product_id' => $res['id'],
                'regular_price' => $variation['regular_price'],
                'image' => array( 'id' => $variation['image'][0]['id'], ),
                'attributes' => $variation['attributes'],
            );
            $wp_rest_request->set_body_params( $variation_rest );
            $new_variation = $this->variations_controler->create_item( $wp_rest_request );
            $res['variations'][] = $new_variation->data;
        }
    }
    return $res;
}

This is used in Kite Print and Dropshipping on Demand plugin, starting from the (soon to be published) version 1.1, in file api/publish_products.php.

There is also a much longer "fast" version called create_products_fast which writes directly to the database, making it potentially less resilient to future WP/WC changes, but it is much faster (few seconds vs. few minutes for our 34 products range on my test computer).

答案 1 :(得分:6)

基于Vedran's answer,这是通过PHP发布WooCommerce产品的最小代码:

$data = [
    'name' => 'Test product',
    'description' => 'Lorem ipsum',
];
$request = new WP_REST_Request( 'POST' );
$request->set_body_params( $data );
$products_controller = new WC_REST_Products_Controller;
$response = $products_controller->create_item( $request );

答案 2 :(得分:3)

这是最合逻辑且最简单的方法。 简单产品使用以下代码:

$objProduct = new WC_Product();

并在代码行下方用于可变产品。

$objProduct = new WC_Product_Variable();

下一步是设置元属性,例如名称,价格等和变体数据(在可变产品的情况下)。

$objProduct->set_name("Product Title");
$objProduct->set_status("publish");  // can be publish,draft or any wordpress post status
$objProduct->set_catalog_visibility('visible'); // add the product visibility status
$objProduct->set_description("Product Description");
$objProduct->set_sku("product-sku"); //can be blank in case you don't have sku, but You can't add duplicate sku's
$objProduct->set_price(10.55); // set product price
$objProduct->set_regular_price(10.55); // set product regular price
$objProduct->set_manage_stock(true); // true or false
$objProduct->set_stock_quantity(10);
$objProduct->set_stock_status('instock'); // in stock or out of stock value
$objProduct->set_backorders('no');
$objProduct->set_reviews_allowed(true);
$objProduct->set_sold_individually(false);
$objProduct->set_category_ids(array(1,2,3)); // array of category ids, You can get category id from WooCommerce Product Category Section of Wordpress Admin

如果要上传产品图片,请使用下面的代码

function uploadMedia($image_url){
    require_once('wp-admin/includes/image.php');
    require_once('wp-admin/includes/file.php');
    require_once('wp-admin/includes/media.php');
    $media = media_sideload_image($image_url,0);
    $attachments = get_posts(array(
        'post_type' => 'attachment',
        'post_status' => null,
        'post_parent' => 0,
        'orderby' => 'post_date',
        'order' => 'DESC'
    ));
    return $attachments[0]->ID;
}
// above function uploadMedia, I have written which takes an image url as an argument and upload image to wordpress and returns the media id, later we will use this id to assign the image to product.
$productImagesIDs = array(); // define an array to store the media ids.
$images = array("image1 url","image2 url","image3 url"); // images url array of product
foreach($images as $image){
    $mediaID = uploadMedia($image); // calling the uploadMedia function and passing image url to get the uploaded media id
    if($mediaID) $productImagesIDs[] = $mediaID; // storing media ids in a array.
}
if($productImagesIDs){
    $objProduct->set_image_id($productImagesIDs[0]); // set the first image as primary image of the product

        //in case we have more than 1 image, then add them to product gallery. 
    if(count($productImagesIDs) > 1){
        $objProduct->set_gallery_image_ids($productImagesIDs);
    }
}

保存产品以获得WooCommerce产品ID

$product_id = $objProduct->save(); // it will save the product and return the generated product id

注意:对于简单产品,上述步骤已足够,以下步骤适用于可变产品或具有属性的产品。

下面的代码用于添加产品属性。<​​/ p>

$attributes = array(
    array("name"=>"Size","options"=>array("S","L","XL","XXL"),"position"=>1,"visible"=>1,"variation"=>1),
    array("name"=>"Color","options"=>array("Red","Blue","Black","White"),"position"=>2,"visible"=>1,"variation"=>1)
);
if($attributes){
    $productAttributes=array();
    foreach($attributes as $attribute){
        $attr = wc_sanitize_taxonomy_name(stripslashes($attribute["name"])); // remove any unwanted chars and return the valid string for taxonomy name
        $attr = 'pa_'.$attr; // woocommerce prepend pa_ to each attribute name
        if($attribute["options"]){
            foreach($attribute["options"] as $option){
                wp_set_object_terms($product_id,$option,$attr,true); // save the possible option value for the attribute which will be used for variation later
            }
        }
        $productAttributes[sanitize_title($attr)] = array(
            'name' => sanitize_title($attr),
            'value' => $attribute["options"],
            'position' => $attribute["position"],
            'is_visible' => $attribute["visible"],
            'is_variation' => $attribute["variation"],
            'is_taxonomy' => '1'
        );
    }
    update_post_meta($product_id,'_product_attributes',$productAttributes); // save the meta entry for product attributes
}

下面的代码用于添加产品变体。

$variations = array(
    array("regular_price"=>10.11,"price"=>10.11,"sku"=>"ABC1","attributes"=>array(array("name"=>"Size","option"=>"L"),array("name"=>"Color","option"=>"Red")),"manage_stock"=>1,"stock_quantity"=>10),
    array("regular_price"=>10.11,"price"=>10.11,"sku"=>"ABC2","attributes"=>array(array("name"=>"Size","option"=>"XL"),array("name"=>"Color","option"=>"Red")),"manage_stock"=>1,"stock_quantity"=>10)
    
);
if($variations){
    try{
        foreach($variations as $variation){
            $objVariation = new WC_Product_Variation();
            $objVariation->set_price($variation["price"]);
            $objVariation->set_regular_price($variation["regular_price"]);
            $objVariation->set_parent_id($product_id);
            if(isset($variation["sku"]) && $variation["sku"]){
                $objVariation->set_sku($variation["sku"]);
            }
            $objVariation->set_manage_stock($variation["manage_stock"]);
            $objVariation->set_stock_quantity($variation["stock_quantity"]);
            $objVariation->set_stock_status('instock'); // in stock or out of stock value
            $var_attributes = array();
            foreach($variation["attributes"] as $vattribute){
                $taxonomy = "pa_".wc_sanitize_taxonomy_name(stripslashes($vattribute["name"])); // name of variant attribute should be same as the name used for creating product attributes
                $attr_val_slug =  wc_sanitize_taxonomy_name(stripslashes($vattribute["option"]));
                $var_attributes[$taxonomy]=$attr_val_slug;
            }
            $objVariation->set_attributes($var_attributes);
            $objVariation->save();
        }
    }
    catch(Exception $e){
        // handle exception here
    }
}

就这样 上面的代码足以添加带有图像,属性和变体的简单或可变WooCommerce产品。

答案 3 :(得分:1)

请参阅woocommerce-with-php-code,其中提供了完整的代码。

正如Avant Garde所说,产品在帖子中添加:

post_type = "product"

答案 4 :(得分:0)

我使用此代码:

$sku = 21333;
$size = 'S';
$stock = 2;
$price_a = 60;
$price_b = 30;

$product_parent = get_product_by_sku($sku);
$product = new WC_Product_Variable($product_parent->id);
$variations = $product->get_available_variations();

// First off all delete all variations
foreach($variations as $prod_variation) {
  $metaid=mysql_query("SELECT meta_id FROM wp_postmeta WHERE post_id = ".$prod_variation['variation_id']);
  while ($row = mysql_fetch_assoc($metaid)) {
    mysql_query("DELETE FROM wp_postmeta WHERE meta_id = ".$row['meta_id']);
  }
  mysql_query("DELETE FROM wp_posts WHERE ID = ".$prod_variation['variation_id']);
}

// Now add new variation
$thevariation = array(
  'post_title'=> '',
  'post_name' => 'product-' . $product_parent->id . '-variation',
  'post_status' => 'publish',
  'post_parent' => $product_parent->id,
  'post_type' => 'product_variation',
  'guid'=>home_url() . '/?product_variation=product-' . $product_parent->id . '-variation'
);
$variation_id = wp_insert_post( $thevariation );
update_post_meta($variation_id, 'post_title', 'Variation #' . $variation_id . ' of '. $product_parent->id);

wp_set_object_terms( $variation_id, $size, 'pa_size' );
update_post_meta($variation_id, 'attribute_pa_size', $size);

update_post_meta($variation_id, '_regular_price', $price_a);
update_post_meta($variation_id, '_downloadable_files', '');
update_post_meta($variation_id, '_download_expiry', '');
update_post_meta($variation_id, '_download_limit', '');
update_post_meta($variation_id, '_sale_price_dates_to', '');
update_post_meta($variation_id, '_sale_price_dates_from', '');
update_post_meta($variation_id, '_backorders', 'no');
update_post_meta($variation_id, '_stock_status', 'instock');
update_post_meta($variation_id, '_height', '');
update_post_meta($variation_id, '_manage_stock', 'yes');
update_post_meta($variation_id, '_width', '');
update_post_meta($variation_id, '_sale_price_dates_from', '');
update_post_meta($variation_id, '_backorders', 'no');
update_post_meta($variation_id, '_stock_status', 'instock');
update_post_meta($variation_id, '_manage_stock', 'yes');
update_post_meta($variation_id, '_height', '');
update_post_meta($variation_id, '_width', '');
update_post_meta($variation_id, '_length', '');
update_post_meta($variation_id, '_weight', '');
update_post_meta($variation_id, '_downloadable', 'no');
update_post_meta($variation_id, '_virtual', 'no');
update_post_meta($variation_id, '_thumbnail_id', '0');
update_post_meta($variation_id, '_sku', '');

update_post_meta($variation_id, '_sale_price', $price_b);
update_post_meta($variation_id, '_price', $price_b);
update_post_meta($product_parent->id, '_min_variation_price', $price_b);
update_post_meta($product_parent->id, '_max_variation_price', $price_b);
update_post_meta($product_parent->id, '_min_price_variation_id', $variation_id);
update_post_meta($product_parent->id, '_max_price_variation_id', $variation_id);
update_post_meta($product_parent->id, '_min_variation_regular_price', $price_a);
update_post_meta($product_parent->id, '_max_variation_regular_price', $price_a);
update_post_meta($product_parent->id, '_min_regular_price_variation_id', $variation_id);
update_post_meta($product_parent->id, '_max_regular_price_variation_id', $variation_id);
update_post_meta($product_parent->id, '_min_variation_sale_price', $price_b);
update_post_meta($product_parent->id, '_max_variation_sale_price', $price_b);
update_post_meta($product_parent->id, '_min_sale_price_variation_id', $variation_id);
update_post_meta($product_parent->id, '_max_sale_price_variation_id', $variation_id);
update_post_meta($product_parent->id, '_price', $price_b);

update_post_meta( $variation_id, '_stock', $stock );
update_post_meta($product_parent->id, 'post_status', 'publish');