Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WooCommerce: Create product by code

My store sells vinyl stickers. Each product (sticker) has a 144 variations (24 colors, 3 sizes and 2 orientation). Each variation is necessary to assign a unique SKU.

Manually populate catalog is unrealistic. I am going to make a form in which the user specifies the name, description, and the main image of the product, as well as the possible sizes and colors. When processing the form i need to create a product and all of its variations.

How to create a product and its variations?

like image 965
Beer Brother Avatar asked Jul 16 '12 11:07

Beer Brother


People also ask

How do I add a product in WooCommerce programmatically?

Add variable products programmatically To create variable products programmatically in WooCommerce, you just need to change the second parameter of the wp_set_object_terms() function: wp_set_object_terms( $post_id, 'variable', 'product_type' ); Similarly, you can define a product as grouped or external.

How do I write code in WooCommerce?

Just go to Appearance > Theme Editor. Make sure that you are editing your Child Theme, and select Theme Functions (functions. php). There you can paste your custom code.


2 Answers

I had a similar situation, here's what I found out.

Products are actually a custom post type (quite obvious! :P), so you can use wp_insert_post to insert a new product. After you insert, you get the id of the new product post type, use update_post_meta to set a meta key and meta value as _visibility and visible respectively. If you don't set the visibility, your newly added product will never be visible in your shop. Alternatively you can set the visibility from the back end as well. For the various sizes of the product, use variations on that product. You can set a different type, price, SKU etc. for each variation. All these are post meta, hence you can use php code to add the variations and stuff. Study the postmeta table to see the key names.

like image 181
Avant Garde Avatar answered Nov 02 '22 23:11

Avant Garde


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).

like image 36
Vedran Šego Avatar answered Nov 02 '22 23:11

Vedran Šego