WooCommerce: Crear producto por código

13 minutos de lectura

avatar de usuario
Hermano de la cerveza

Mi tienda vende pegatinas de vinilo. Cada producto (pegatina) tiene 144 variaciones (24 colores, 3 tamaños y 2 orientaciones). Cada variación es necesaria para asignar un SKU único.

Rellenar manualmente el catálogo no es realista. Voy a hacer un formulario en el que el usuario especifique el nombre, la descripción y la imagen principal del producto, así como los posibles tamaños y colores. Al procesar el formulario, necesito crear un producto y todas sus variaciones.

¿Cómo crear un producto y sus variaciones?

  • ¿Necesita crear una imagen o simplemente imprimir las posibles opciones?

    – Peón

    16 de julio de 2012 a las 11:50

  • Ahora que hay una API REST V2, recomendaría usarla para crear productos. La API puede iniciar sesión como un usuario diferente y se adapta a todas las sutilezas que pueden pasarse por alto al construir un producto manualmente. También implica simplemente juntar una sola estructura de datos grande y enviarla para que se configure en una sola acción.

    – Jasón

    28 de febrero de 2015 a las 23:41

  • WooCommerce ha introducido nuevos objetos CRUD en 3.0; se recomienda enfáticamente que comience a usarlos, en lugar de usar funciones puras de WordPress para actualizar datos de ingeniería inversa. github.com/woocommerce/woocommerce/wiki/CRUD-Objects-in-3.0

    – Pavel Lishin

    29 de abril de 2019 a las 18:09

avatar de usuario
vanguardia

Tuve una situación similar, esto es lo que descubrí.

Los productos son en realidad un tipo de publicación personalizada (¡bastante obvio! :P), así que puedes usar wp_insert_post para insertar un nuevo producto. Después de insertar, obtiene la identificación del nuevo tipo de publicación del producto, use update_post_meta para establecer una clave meta y un valor meta como _visibility y visible respectivamente. Si no configura la visibilidad, su producto recién agregado nunca será visible en su tienda. Alternativamente, también puede configurar la visibilidad desde el back-end. Para los distintos tamaños del producto, utilice variaciones de ese producto. Puede establecer un tipo, precio, SKU, etc. diferente para cada variación. Todos estos son post meta, por lo tanto, puede usar el código php para agregar las variaciones y demás. Estudiar el postmeta tabla para ver los nombres de las claves.

  • cuando me pongo update_post_meta( $new_product_post_id, '_visibility', 'hidden' ); pero en la página de back-end de detalles del producto. todavía muestra visible valor. Qué equivocado ?

    – huykon225

    12 de junio de 2017 a las 2:36

avatar de usuario
Vedran Sego

Como escribió Jason en su comentario, la API REST es el camino a seguir aquí. Esto se puede hacer incluso sin solicitudes HTTP REST, lo que hace que funcione incluso en instalaciones de WordPress que tienen su interfaz REST deshabilitada.

Aquí hay una función simple que hice para este propósito:

$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);
}

Aquí, $rest_request es una matriz que normalmente enviaría a través de REST (consulte los documentos aquí).

los $products_controler variable es global porque necesitaba llamar a esta función varias veces y no quería volver a crear el objeto cada vez. Siéntete libre de hacerlo local.

Esto funciona para todo tipo de productos (simples, agrupados, variables,…) y debería ser más resistente a los cambios internos de WooCommerce que agregar los productos manualmente a través de wp_insert_post y update_post_meta.

Editar: Dado que esta respuesta todavía recibe un voto a favor ocasional, aquí hay una WooCommerce 3.0+ actualizar. El cambio es que las variaciones ya no se agregan automáticamente, por lo que tenemos que hacerlo nosotros mismos.

Esta es la versión actual de la función:

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;
}

Esto se usa en Kite Print y Dropshipping bajo demanda complemento, a partir de la versión 1.1 (que pronto se publicará), en el archivo api/publish_products.php.

También hay una versión “rápida” mucho más larga llamada create_products_fast que escribe directamente en la base de datos, lo que lo hace potencialmente menos resistente a futuros cambios de WP/WC, pero es mucho más rápido (pocos segundos frente a pocos minutos para nuestra gama de 34 productos en mi computadora de prueba).

  • hola la version create_products_fast es parte del WC o se usa en el complemento Kite Print?

    – Jeans K. Real

    23 de noviembre de 2017 a las 13:48

  • @JeansK.Real Es una función en el complemento de Kite (ahora descontinuado), en el que todas las solicitudes SQL normalmente realizadas a través de muchas funciones WP (unos pocos cientos de llamadas en nuestro caso) se agruparon en solo 5 o 6 llamadas SQL masivas, haciendo es increíblemente rápido, pero tampoco muy resistente a los cambios de WP/WC. Como respaldo para tales casos, teníamos una configuración que activaría o desactivaría la función (en el último caso, se utilizó la función anterior).

    – Vedran Sego

    24 de noviembre de 2017 a las 12:36

Esta es la forma más lógica y fácil. Producto simple use el siguiente código:

$objProduct = new WC_Product();

y para uso de productos variables debajo de la línea de código.

$objProduct = new WC_Product_Variable();

El siguiente paso es establecer las propiedades meta como nombre, precio, etc. y datos de variantes (en caso de producto 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

El siguiente código se usa si desea cargar imágenes del producto

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);
    }
}

guarde el producto para obtener el ID de producto de WooCommerce

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

Nota: para un producto simple, los pasos anteriores son suficientes, los pasos a continuación son para productos variables o productos que tienen atributos.

El siguiente código se usa para agregar atributos del producto.

$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
}

El siguiente código se usa para agregar variantes de productos.

$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
    }
}

Eso es todo El código anterior es suficiente para agregar un producto de WooCommerce simple o variable con imágenes, atributos y variantes.

avatar de usuario
Sófivoro

Basado en la respuesta de Vedran, aquí está el código mínimo para publicar un producto de WooCommerce a través de PHP:

$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 );

avatar de usuario
señor

Por favor refiérase a woocommerce-con-php-codedonde se proporciona el código completo.

Como decía Avant Garde, los productos se añaden en post con:

post_type = "product"

avatar de usuario
vijay

Yo uso este código:

$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');

¿Ha sido útil esta solución?