web-dev-qa-db-fra.com

Créer par programme une variante de produit WooCommerce avec de nouvelles valeurs d'attribut

J'ai créé un produit variable (produit "parent") dans Woocommerce version 3+. À partir d'un plugin Wordpress, j'aimerais créer par programmation les variantes de produit (produit "enfants") avec de nouvelles valeurs d'attribut. 

Les attributs de variation sont déjà définis dans Woocommerce. 
Ainsi, chaque fois qu'une variante est créée, les valeurs du nouvel attribut doivent également être créées par programme et définies dans le produit Variable parent.

Comment cela peut-il être fait? c'est possible?


Mise à jour: J'avais écrit plus de lignes de codes à ce sujet que je souhaitais, et essayé beaucoup de choses pour le résoudre, en utilisant des objets woocommerce, et ajouté des données manquantes sur les termes, termmeta, la relation de terme avec post, dans la base de données Objet wordpress database - mais rien n’a suffi pour le faire fonctionner. Et je ne pouvais pas cerner les points où je me suis trompé - c'est pourquoi je ne pouvais pas fournir un problème plus étroit - des choses pour lesquelles le stackoverflow est plus destiné.

7
Cedric

Mise à jour septembre 2018: Gestion de la création de taxonomie _ {(Merci à Carl F. Corneil)} _

A partir d'un ID de produit variable défini Vous trouverez ci-dessous, une fonction personnalisée qui ajoutera (créera) une variante de produit. La variable produit parent doit avoir défini les attributs nécessaires.

Vous devrez fournir des informations telles que:

  • le tableau d'attributs/valeurs
  • le sku, les prix et le stock….

Ces données doivent être stockées dans un tableau multidimensionnel formaté (voir un exemple à la fin)}.

Cette fonction vérifiera si les valeurs d'attributs (nom du terme) existent déjà et si ce n'est pas le cas:.

Le code de fonction personnalisé:

/**
 * 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_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
}

Le code va dans le fichier function.php de votre thème enfant actif (ou de votre thème) ou également dans tout fichier plugin.

Utilisation (exemple avec 2 attributs):

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

Testé et fonctionne.

Partie 2:Créer par programme un produit variable et deux nouveaux attributs dans Woocommerce

Vous obtiendrez ceci dans le backend:

 enter image description here

Et cela fonctionnera parfaitement en avant.

30
LoicTheAztec

En développant la réponse de LoicTheAztec, vous pouvez vérifier si la combinaison d'attributs existe avec la modification suivante de son code.

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

    }

    // ...

}

Exemple d'utilisation

// 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 );
2
Davey

Vous pourriez rencontrer un problème ici si la taxonomie du produit n’est pas enregistrée auparavant ailleurs. Si vous voulez vous assurer que la taxonomie existe, vous pouvez ajouter une condition à la réponse de LoicTheAztec.

Quelque chose comme ça.

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

    }
...
1
Carl F. Corneil

Je vais simplement vous en parler, car je ne parviens pas à obtenir l'un des exemples ci-dessus. Ne me demandez pas pourquoi, car les autres semblent avoir du succès. J'ai donc adopté l'approche minimaliste et essayé de comprendre l'essentiel pour un attribut de produit + une variation (en le créant manuellement dans wp et en regardant la base de données) et je suis arrivé à cela.

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

Ceci n'utilise pas d'attributs de produit globaux, mais ceux spécifiques à un article. J'espère que cela aidera quelqu'un, car j'étais sur le point de me déchirer les cheveux avant de le faire fonctionner.

1
PKSWE

cela fonctionne mais nécessite quelques corrections (2 virgules dans le tableau de fonctions), j'ai édité une partie du code selon mes besoins.

(travaille sur wp 4.9 | wc 3.5)

Tout d'abord, les produits doivent avoir l'attribut déjà créé et associé, ma taxonomie est "pa_r" nom convivial "R" attribut backend associé img

la fonction avec la 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
}

J'ai créé un tableau avec les données dont j'ai besoin dans les variantes [id_post, attribut, 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]
);

et le foreach pour créer dynamiquement toutes les variations de mes produits

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

Si vous souhaitez générer des produits à tester dans WooCommerce, vous pouvez utiliser WooCommerce Smooth Generator, fabriqué par WooCommerce lui-même.

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

Exemple:

// 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

Si vous souhaitez créer des produits par programmation, vous pouvez classer la catégorie de produit en fonction de vos besoins.

0
Lucas Bustamante