web-dev-qa-db-ger.com

Erstellen Sie programmgesteuert eine WooCommerce-Produktvariation mit neuen Attributwerten

Ich habe in Woocommerce Version 3+ ein variables Produkt ("Mutterprodukt") erstellt. Von einem Wordpress-Plugin aus möchte ich die Produktvariationen ("Kinder" -Produkt) mit neuen Attributwerten programmgesteuert erstellen. 

Die Variationsattribute sind in Woocommerce bereits festgelegt. 
Jedes Mal, wenn eine Variation erstellt wird, sollten die Werte des neuen Attributs auch programmgesteuert erstellt und im übergeordneten Variablenprodukt festgelegt werden.

Wie kann das gemacht werden? ist es möglich?


Update: Ich hatte mehr Codezeilen darüber geschrieben, die ich wollte, und habe viele Dinge versucht, um das Problem zu lösen, indem er Woocommerce-Objekte verwendete. Außerdem wurden fehlende Daten zu Termini, Termmeta, der Beziehung zwischen Term und Post in der Datenbank hinzugefügt WordPress-Datenbankobjekt - aber nichts hat ausgereicht, damit es funktioniert. Und ich konnte nicht genau feststellen, wo ich falsch lief - deshalb konnte ich kein engeres Problem darstellen - Dinge, für die Stackoverflow eher geeignet ist.

7
Cedric

Update September 2018: Handhabung der Taxonomie (Danke an Carl F. Corneil)

Aus einer definierten variablen Produkt-ID finden Sie unten eine benutzerdefinierte Funktion, mit der eine Produktvariante hinzugefügt (erstellt) wird. Das übergeordnete Produkt der Variablen muss die erforderlichen Attribute dafür festgelegt haben.

Sie müssen einige Informationen angeben wie:

  • das Array von Attributen/Werten
  • die Sku, Preise und Lager….

Diese Daten müssen in einem formatierten mehrdimensionalen Array (siehe Beispiel am Ende)} gespeichert werden.

Diese Funktion prüft, ob die Attributwerte (Begriffsname) bereits vorhanden sind, und wenn nicht: - wird sie für das Produktattribut - im übergeordneten Variablenprodukt festgelegt.

Der benutzerdefinierte Funktionscode:

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

Code wird in function.php -Datei Ihres aktiven untergeordneten Designs (oder Designs) oder auch in einer beliebigen Plugin-Datei gespeichert.

Verwendung (Beispiel mit 2 Attributen):

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

Getestet und funktioniert.

Teil 2:Erstellen Sie programmgesteuert ein variables Produkt und zwei neue Attribute in Woocommerce

Sie erhalten dies im Backend:

 enter image description here

Und es wird perfekt im Frontend funktionieren.

30
LoicTheAztec

Wenn Sie die Antwort von LoicTheAztec erweitern, können Sie mit der folgenden Änderung des Codes überprüfen, ob die Attributkombination vorhanden ist.

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

    }

    // ...

}

Verwendungsbeispiel

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

Sie könnten hier auf ein Problem stoßen, wenn die Taxonomie des Produkts zuvor nicht woanders registriert wurde. Wenn Sie sicherstellen möchten, dass die Taxonomie vorhanden ist, können Sie der Antwort von LoicTheAztec eine Bedingung hinzufügen.

Etwas wie das.

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

Ich werde das hier nur rausschmeißen, da ich keines der oben genannten Beispiele zum Laufen bringen konnte. Fragen Sie mich nicht, warum andere Leute Erfolg haben. Also habe ich den minimalistischen Ansatz gewählt und versucht, das Nötigste für ein Produktattribut + Variation herauszufinden (indem ich es manuell in wp erstellt habe und die DB anschaue).

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

Hierbei werden keine globalen Produktattribute verwendet, sondern artikelspezifische. Ich hoffe, es hilft jemandem, als ich ungefähr bereit war, mir die Haare herauszureißen, bevor es funktioniert.

1
PKSWE

es funktioniert, benötigt aber ein paar Korrekturen (2 Kommas im fuctions-Array). Ich habe einige der Codes an meine Bedürfnisse angepasst.

(Arbeit an wp 4.9 | wc 3.5)

Zuerst muss das Produkt bereits mit dem Attribut erstellt und verknüpft sein. Meine Taxonomie lautet "pa_r", der Anzeigename "R" Backend-Attribut zugeordnetes Bild

die Funktion mit der Korrektur

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
}

Ich habe ein Array mit den Daten erstellt, die ich in den Variationen benötige [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]
);

und der foreach, alle variationen meiner produkte dynamisch zu erstellen

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

Wenn Sie Produkte zum Testen in WooCommerce generieren möchten, können Sie den von WooCommerce selbst erstellten WooCommerce Smooth Generator verwenden.

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

Beispiel:

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

Wenn Sie Produkte programmgesteuert erstellen möchten, können Sie die Produktklasse Ihren Bedürfnissen anpassen.

0

die obige Antwort (LoicTheAztec) hat mir sehr geholfen, aber es gab einige Probleme, anstatt sie zu benutzen

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

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

da die Taxonomie bereits geändert wurde und dies zu Problemen beim Aktualisieren von Post-Meta führt, nachdem diese Aktualisierungswerte geändert wurden und nicht automatisch in der Admin-Produktvariation ausgewählt wurde, funktioniert sie hervorragend.