【问题标题】:How to set attribute as variation in Woocommerce如何在 Woocommerce 中将属性设置为变体
【发布时间】:2014-02-10 00:45:39
【问题描述】:

我正在创建一个前端表单,允许用户使用预定义的属性和变体从前端向我的商店发布可变产品。

我发现这个非常有用的问题:here 它向我展示了如何将产品类型设置为变量并在产品数据的属性部分分配我的预定义属性。

但是,当我在 Wordpress/Woocommerce 的后端并编辑产品时,我点击了变体并且没有设置任何内容,我查看了属性,并且我的“分辨率”属性设置了我的 3 个项目。

如何将其设置为实际将这些属性设置为我的表单变体的位置?我需要使用 wp_insert_post 吗?在 phpmyadmin 中看起来就像产品变体被分配给了 parent_id(产品 id)并且帖子类型是 product_varition 等等。

$new_post = array(
'post_title' => esc_attr(strip_tags($_POST['postTitle'])),
'post_content' => esc_attr(strip_tags($_POST['postContent'])),
'post_status' => 'publish',
'post_type' => 'product',
'tags_input' => array($tags)
);

$skuu = rand();
$post_id = wp_insert_post($new_post);
update_post_meta($post_id, '_sku', $skuu );

//my array for setting the attributes
$avail_attributes = array(
    'high-resolution',
    'medium-resolution',
    'low-resolution'
);

//Sets the attributes up to be used as variations but doesnt actually set them up as variations
wp_set_object_terms ($post_id, 'variable', 'product_type');
wp_set_object_terms( $post_id, $avail_attributes, 'pa_resolution' );


$thedata = array(
'pa_resolution'=> array(
                'name'=>'pa_resolution',
                'value'=>'',
                'is_visible' => '1',
                'is_variation' => '1',
                'is_taxonomy' => '1'
                )
);
update_post_meta( $post_id,'_product_attributes',$thedata);

update_post_meta( $post_id, '_visibility', 'search' );
update_post_meta( $post_id, '_stock_status', 'instock');

所以为了清楚起见(我容易混淆),上面确实从前端创建了我的可变产品,当我在后端查看产品时,它是一个可变产品,它具有分辨率属性集和有我的 3 个术语(高分辨率、中分辨率、低分辨率)作为属性。我只需要更进一步,将它们实际设置为变体,以便人们可以下订单。

【问题讨论】:

    标签: php wordpress woocommerce


    【解决方案1】:

    我通过使用 update_post_meta 和 wp_insert_post 让它适合我的情况。因为我已经设置了属性和术语,所以我只需要一种添加到上述代码的方法,以便在创建产品时,它不仅会将属性分配给产品,而且会将它们作为变体插入数据库中。

    这是我的解决方案:

    //insert variations post_type
    $i=1;
    while ($i<=3) {
    $my_post = array(
          'post_title'    => 'Variation #' . $i . ' of ' . esc_attr(strip_tags($_POST['postTitle'])),
          'post_name'     => 'product-' . $post_id . '-variation-' . $i,
          'post_status'   => 'publish',
          'post_parent'   => $post_id,
          'post_type'     => 'product_variation',
          'guid'          =>  home_url() . '/?product_variation=product-' . $post_id . '-variation-' . $i
        );
    
        // Insert the post into the database
        wp_insert_post( $my_post );
    
        $variable_id = $post_id + 1;
        $variable_two = $variable_id + 1;
        $variable_three = $variable_two + 1;
    
        update_post_meta( $variable_id, 'attribute_pa_resolution', 'high-resolution');
        update_post_meta( $variable_id, '_price', 8.50 );
        update_post_meta( $variable_id, '_regular_price', '8.50');
    
        update_post_meta( $variable_two, 'attribute_pa_resolution', 'medium-resolution');
        update_post_meta( $variable_two, '_price', 5.50 );
        update_post_meta( $variable_two, '_regular_price', '5.50');
    
        update_post_meta( $variable_three, 'attribute_pa_resolution', 'low-resolution');
        update_post_meta( $variable_three, '_price', 3.50 );
        update_post_meta( $variable_three, '_regular_price', '3.50');
    
        $i++;
        }
    

    【讨论】:

    • 感谢您发布此信息。我有一个你可能知道的问题。我正在使用与此类似的东西,但来自 csv 文件。我添加了所有属性,它们在编辑产品时显示为正确的产品,具有适当的价值和价格等。问题是它们没有显示在商店页面上。仅当我通过编辑产品查看产品时。当我最初添加属性时,我必须删除 wc_attribute_taxonomies 瞬态,否则它们不会出现。知道为什么可变产品不会显示在商店页面中吗?
    • 当您使用 wp_insert_post 时,它会返回新的 post_id
    • 完全符合我的要求。谢谢!
    • 使用最新的 WooCommerce 版本,此代码不适用于我。
    【解决方案2】:

    过去两天我一直在努力在我的插件中实现在 Woocommerce 中设置产品变体的能力。

    我设法在 DB 中获取了所有正确的数据,但 Woocommerce 并没有像我想象的那样检索。

    问题是存储在 wp_options 表中的“瞬态”。

    这是让我启动并运行 WC 2.6.0 的代码:

    基于所选属性创建变化($_POST['term_id_arr'] 是从前端选择的用于创建产品的所有属性的列表。很抱歉,我还不能在堆栈上发布图像。Front-end form with variations created )

    $opzioni_arr=$_POST['term_id_arr'];
    $qta = count($opzioni_arr);
    if ($qta>0){
        $ID = $post_id;
        //make product type be variable:
        wp_set_object_terms ($ID,'variable','product_type');
    
    
        foreach ($opzioni_arr as $opzioni_val){
            $new_arr = explode("/",$opzioni_val);
            $att_taxonomy = $new_arr[0];
            $att_slug = $new_arr[1];
            $att_id =$new_arr[2];
            $att_arr[$att_taxonomy][$att_id]=$att_slug;
            $att_due_arr[$att_taxonomy][$att_taxonomy.'*'.$att_id]=$att_slug;
        }
        //################### Add attributes to main product: ####################
        foreach ($att_arr as $att_arr_key=>$att_arr_val){
    
            //Array for setting attributes
            unset ($avail_attributes);
            foreach ($att_arr_val as $key_two=>$val_two){
                $avail_attributes[] = $val_two;
            }
    
            wp_set_object_terms($ID, $avail_attributes, $att_arr_key);
    
            $thedata [$att_arr_key]= Array(
                                                    'name'=>$att_arr_key,
                                                    'value'=>'',
                                                    'is_visible' => 1, 
                                                    'is_variation' => 1,
                                                    'is_taxonomy' => 1,
                                                    'position' => '1'
                                                );
    
        }
    
            update_post_meta( $ID,'_product_attributes',$thedata);
        //########################## Done adding attributes to product #################
    
        //function to create combinations from attributes
        $combinations=lasap_get_combinations($att_due_arr);     
    
        foreach ($combinations as $key=>$val){
        // Start creating variations
        // The variation is simply a post
        // with the main product set as its parent
        // you might want to put that in a loop or something
        // to create multiple variations with multiple values
        $parent_id = $ID;
        $variation = array(
                            'post_title'   => 'Prodotto #' . $parent_id . ' Variante',
                            'post_content' => '',
                            'post_status'  => 'publish',
                            'post_parent'  => $parent_id,
                            'post_type'    => 'product_variation'
                        );
        // The variation id
        $variation_id = wp_insert_post( $variation );
    
    
        // Regular Price ( you can set other data like sku and sale price here )
    
        update_post_meta($variation_id, '_sku', $sku);
    
        update_post_meta($variation_id, '_regular_price', $regular_price);
    
        update_post_meta($variation_id, '_sale_price', $sale_price);
        update_post_meta($variation_id, '_sale_price_dates_from', $datasaldodal_time);
        update_post_meta($variation_id, '_sale_price_dates_to', $datasaldoal_time);
    
        if (($sale_price!='' AND ($sale_price<=$regular_price))){$price=$sale_price;} else {$price=$regular_price;}
        update_post_meta($variation_id, '_price', $price);
    
        update_post_meta($variation_id, '_thumbnail_id', $thumbnail_id);
    
        update_post_meta($variation_id, '_manage_stock', $manage_stock);
        update_post_meta($variation_id, '_stock_status', $stock_status);
        update_post_meta($variation_id, '_stock', $stock);
        update_post_meta($variation_id, '_stock_soglia', $stock_soglia);
        update_post_meta($variation_id, '_backorders', $backorders);
    
    
        foreach ($val as $chiave=>$valore){
                $exp = explode ("*", $chiave);
                $attributo_nome = $exp[0];
                update_post_meta( $variation_id, 'attribute_' . $attributo_nome, $valore );
                $split_attributo = explode("_", $attributo_nome);
                $attributo_nome_due = $split_attributo[1];
                echo "<p>Variante #$variation_id: $attributo_nome_due ($valore)</p>";
    
            }
        }
        do_action( 'product_variation_linked', $variation_id );
        // Update parent if variable so price sorting works and stays in sync with the cheapest child
        lasap_woo_sync_varianti ($post_id, $stock_status_before);   
    
    }
    delete_transient( 'wc_product_children_' . $parent_id );
    

    更新变化(例如价格、销售价格等...)。

        $sku_arr = $_POST['sku'];
    $prezzolistino_arr = $_POST['prezzolistino']; //regular_price
    $prezzosaldo_arr = $_POST['prezzosaldo']; //sale_price
    $datasaldoal_arr = $_POST['datasaldoal']; //sale_date_to
    $datasaldodal_arr = $_POST['datasaldodal']; //sale_date_from
    $manage_stock_arr = $_POST['manage_stock'];
    $stock_arr = $_POST['stock'];
    $stock_soglia_arr = $_POST['stock_soglia'];
    $backorders_arr = $_POST['backorders'];
    
    foreach ($sku_arr as $varID=>$sku){
        $prezzolistino = $prezzolistino_arr[$varID];
        $prezzosaldo = $prezzosaldo_arr[$varID];
        if (($prezzosaldo!='' AND ($prezzosaldo<=$prezzolistino))){$prezzoesposto=$prezzosaldo;} else {$prezzoesposto=$prezzolistino;}
            $prezzoesposto = $prezzoesposto * 1;
        $datasaldoal = $datasaldoal_arr[$varID];
        $datasaldodal = $datasaldodal_arr[$varID];
        $manage_stock = $manage_stock_arr[$varID];
        $stock = $stock_arr[$varID];
        $stock_soglia = $stock_soglia_arr[$varID];
        $backorders = $backorders_arr[$varID];
        switch ($manage_stock){
            case "on": $manage_stock = "yes"; break;
            default : $manage_stock = "no";
        }
        switch ($backorders){
            case "on": $backorders = "yes"; break;
            default : $backorders = "no";
        }
    
        update_post_meta ($varID, '_sku', $sku);
        update_post_meta ($varID, '_regular_price', $prezzolistino);
        update_post_meta ($varID, '_sale_price', $prezzosaldo);
        update_post_meta ($varID, '_price', $prezzoesposto);
        update_post_meta ($varID, '_sale_price_dates_to', $datasaldoal);
        update_post_meta ($varID, '_sale_price_dates_from', $datasaldodal);
        update_post_meta ($varID, '_manage_stock', $manage_stock);
        update_post_meta ($varID, '_stock', $stock);
        update_post_meta ($varID, '_stock_soglia', $stock_soglia);
        update_post_meta ($varID, '_backorders', $backorders);
    }
    // Update parent if variable so price sorting works and stays in sync with the cheapest child
        $tipo = $_POST['tipo'];//this is a value to check if I am updating main product or its children
        if ($tipo != 'parent'){
            lasap_woo_sync_varianti ($post_id, $stock_status_before);
        }
    

    删除变体

    $ID_arr = $_POST['ID'];
    foreach ($ID_arr as $ID){
        $res = wp_delete_post($ID, true);
    }
    $variazioni = lasap_woo_check_variazioni($post_id);
    
    if ($variazioni > 0){
        // Update parent if variable so price sorting works and stays in sync with the cheapest child
        lasap_woo_sync_varianti ($post_id, $stock_status_before);
    } else {
        //clean up main product
        delete_post_meta($post_id, '_product_attributes');
        delete_post_meta($post_id, '_min_variation_price');
        delete_post_meta($post_id, '_max_variation_price');
        delete_post_meta($post_id, '_min_price_variation_id');
        delete_post_meta($post_id, '_max_price_variation_id');
        delete_post_meta($post_id, '_min_variation_regular_price');
        delete_post_meta($post_id, '_max_variation_regular_price');
        delete_post_meta($post_id, '_min_regular_price_variation_id');
        delete_post_meta($post_id, '_max_regular_price_variation_id');
        delete_post_meta($post_id, '_min_variation_sale_price');
        delete_post_meta($post_id, '_max_variation_sale_price');
        delete_post_meta($post_id, '_min_sale_price_variation_id');
        delete_post_meta($post_id, '_max_sale_price_variation_id');
    
        update_post_meta($post_id, '_stock_status', 'instock');
        wp_set_object_terms ($post_id,'simple','product_type');
        wc_delete_product_transients( $post_id );
    }
    

    调用同步的函数....

    function lasap_woo_sync_varianti ($post_id, $stock_status_before){
    //https://docs.woocommerce.com/wc-apidocs/class-WC_Product_Variable.html
    //WC_Product_Variable::variable_product_sync( $post_id );//sync variable product prices with the children lowest/highest (calls :sync)
    //WC_Product_Variable::sync_stock_status( $post_id );//sync the variable product stock status with children
    //WC_Product_Variable::sync_attributes( $post_id );//sync the variable product's attributes with the variations (called by :sync)
    WC_Product_Variable::sync( $post_id );//sync the variable product with it's children
    wc_delete_product_transients( $post_id );
    lasap_get_variation_prices ($post_id);
    
    $stock_status_after = get_post_meta($post_id, '_stock_status', true);
    update_post_meta($post_id, '_stock_status', $stock_status_before);
    

    }

    设置瞬态的函数(从 woocommerce\includes\class-wc-product-variable.php 提取)

    function lasap_get_variation_prices( $post_id, $display = false ) {
        global $wp_filter, $woocommerce, $wpdb;
        $_product   = wc_get_product( $post_id );
        /**
         * Transient name for storing prices for this product (note: Max transient length is 45)
         * @since 2.5.0 a single transient is used per product for all prices, rather than many transients per product.
         */
        $transient_name = 'wc_var_prices_' . $post_id;
    
        /**
         * Create unique cache key based on the tax location (affects displayed/cached prices), product version and active price filters.
         * DEVELOPERS should filter this hash if offering conditonal pricing to keep it unique.
         * @var string
         */
        if ( $display ) {
            $price_hash = array( get_option( 'woocommerce_tax_display_shop', 'excl' ), WC_Tax::get_rates() );
        } else {
            $price_hash = array( false );
        }
    
        $filter_names = array( 'woocommerce_variation_prices_price', 'woocommerce_variation_prices_regular_price', 'woocommerce_variation_prices_sale_price' );
    
        foreach ( $filter_names as $filter_name ) {
            if ( ! empty( $wp_filter[ $filter_name ] ) ) {
                $price_hash[ $filter_name ] = array();
    
                foreach ( $wp_filter[ $filter_name ] as $priority => $callbacks ) {
                    $price_hash[ $filter_name ][] = array_values( wp_list_pluck( $callbacks, 'function' ) );
                }
            }
        }
    
        $price_hash = md5( json_encode( apply_filters( 'woocommerce_get_variation_prices_hash', $price_hash, $_product, $display ) ) );
    
    
                // If the value has already been generated, we don't need to grab the values again.
        if ( empty( $post_id->prices_array[ $price_hash ] ) ) {
    
            // Get value of transient
            $prices_array = array_filter( (array) json_decode( strval( get_transient( $transient_name ) ), true ) );
    
            // If the product version has changed, reset cache
    
            if ( empty( $prices_array['version'] ) || $prices_array['version'] !== WC_Cache_Helper::get_transient_version( 'product' ) ) {
                $post_id->prices_array = array( 'version' => WC_Cache_Helper::get_transient_version( 'product' ) );
            }
    
            // If the prices are not stored for this hash, generate them
            //if ( empty( $prices_array[ $price_hash ] ) ) {
                if ( 1>0 ) {
                $prices         = array();
                $regular_prices = array();
                $sale_prices    = array();
                $variation_ids  = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_type='product_variation' AND post_status='publish' AND post_parent=$post_id", 0);
    
                foreach ( $variation_ids as $variation_id ) {
                    $post_meta = get_post_meta($variation_id);
                        $price         = $post_meta['_price'][0];
                        $regular_price = $post_meta['_regular_price'][0];
                        $sale_price    = $post_meta['_sale_price'][0];
    
                        // Skip empty prices
                        if ( '' === $price ) {
                            continue;
                        }
    
                        // If sale price does not equal price, the product is not yet on sale
                        if ( $sale_price === $regular_price || $sale_price !== $price ) {
                            $sale_price = $regular_price;
                        }
    
                        // If we are getting prices for display, we need to account for taxes
                        if ( $display ) {
                            if ( 'incl' === get_option( 'woocommerce_tax_display_shop' ) ) {
                                $price         = '' === $price ? ''         : $variation->get_price_including_tax( 1, $price );
                                $regular_price = '' === $regular_price ? '' : $variation->get_price_including_tax( 1, $regular_price );
                                $sale_price    = '' === $sale_price ? ''    : $variation->get_price_including_tax( 1, $sale_price );
                            } else {
                                $price         = '' === $price ? ''         : $variation->get_price_excluding_tax( 1, $price );
                                $regular_price = '' === $regular_price ? '' : $variation->get_price_excluding_tax( 1, $regular_price );
                                $sale_price    = '' === $sale_price ? ''    : $variation->get_price_excluding_tax( 1, $sale_price );
                            }
                        }
    
                        $prices[ $variation_id ]         = wc_format_decimal( $price, wc_get_price_decimals() );
                        $regular_prices[ $variation_id ] = wc_format_decimal( $regular_price, wc_get_price_decimals() );
                        $sale_prices[ $variation_id ]    = wc_format_decimal( $sale_price . '.00', wc_get_price_decimals() );
    
                }
    
                asort( $prices );
                asort( $regular_prices );
                asort( $sale_prices );
    
                $prices_array[ $price_hash ] = array(
                    'price'         => $prices,
                    'regular_price' => $regular_prices,
                    'sale_price'    => $sale_prices,
                );
                echo "<br> 659) ";mostra_array($prices_array);
                set_transient( $transient_name, json_encode( $prices_array ), DAY_IN_SECONDS * 30 );
            }
    
            /**
             * Give plugins one last chance to filter the variation prices array which has been generated.
             */
            $post_id->prices_array[ $price_hash ] = apply_filters( 'woocommerce_variation_prices', $prices_array[ $price_hash ], $post_id, $display );
        }
    
    
    }
    

    我用来检查产品是否有变化(退货数量)的功能

    function lasap_woo_check_variazioni($post_id){
    global $wpdb;
    $qry_var="  SELECT COUNT(ID) FROM $wpdb->posts WHERE
                    post_type='product_variation' AND
                    post_parent=$post_id AND
                    post_status='publish'";
    $res_var=$wpdb->get_var($qry_var);
    return $res_var;
    

    }

    在这一切之后,又出现了另一个问题(它永远不会发生,不是吗?):我还没弄清楚为什么,但在更新变体之后,父产品 post_meta '_stock_status' 总是设置为 'outofstock'。

    我已修补此问题,在开始时使用 get_post_meta 检索正确状态并将其值传递给函数 lasap_woo_sync_varianti。

    非常感谢任何改进,希望这将帮助某人节省他/她的时间!

    在 WC 2.6.13 上经过测试和工作。见链接here

    【讨论】:

      【解决方案3】:
      update_post_meta( $post_id, '_visibility', PARAM' ) 
      

      它将有 3 或 4 个参数:隐藏 |搜索 |目录 |可见

      尝试将您的_visibility 设置为“可见”参数。

      【讨论】:

      • 是的,这是昨晚想出来的……不过,感谢您的发帖。现在试图弄清楚如何触发链接所有变体。当我正在导入属性时,然后在输入要使用的属性和变体的单元格中,这会创建每个变体作为它自己的变体,我宁愿将它们全部链接起来。大号 - 黑色、大号 - 橙色等
      【解决方案4】:

      随着 woocommerce 的最后实现,此代码不起作用。

      当我使用此代码时:

      $my_post = array(
      'post_title'    => 'Variation #' . $i . ' of ' . esc_attr(strip_tags($_POST['postTitle'])),
      'post_name'     => 'product-' . $post_id . '-variation-' . $i,
      'post_status'   => 'publish',
      'post_parent'   => $post_id,
      'post_type'     => 'product_variation',
      'guid' =>  home_url() . '/?product_variation=product-' . $post_id . '-variation-' . $i
      );
      wp_insert_post( $my_post );
      

      默认插入三个变体,我无法删除或插入另一个变体。

      有什么办法吗?

      【讨论】:

        猜你喜欢
        • 2021-09-28
        • 1970-01-01
        • 1970-01-01
        • 2015-02-18
        • 1970-01-01
        • 1970-01-01
        • 2020-07-05
        • 2020-07-20
        • 2018-09-15
        相关资源
        最近更新 更多