简体   繁体   English

如何将变体库存状态添加到 Woocommerce 产品变体下拉列表

[英]How to add variation stock status to Woocommerce product variation dropdown

I would like to show the stock status (eg. In Stock / Out of Stock) for each product variation shown in the drop down list of variations on the Woocommerce Product Page.我想显示 Woocommerce 产品页面上变体下拉列表中显示的每个产品变体的库存状态(例如,有货/缺货)。 I have copied the relevant function to my theme's functions.php file, and can edit the content, but am unsure how to pull out the required stock status for each variation.我已将相关函数复制到我的主题的functions.php 文件中,并且可以编辑内容,但我不确定如何为每个变体提取所需的库存状态。

// Updated Woocommerce Product Variation Select 

if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {

    /**
     * Output a list of variation attributes for use in the cart forms.
     *
     * @param array $args
     * @since 2.4.0
     */

     /*

    function wc_dropdown_variation_attribute_options( $args = array() ) {
        $args = wp_parse_args( apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ), array(
            'options'          => false,
            'attribute'        => false,
            'product'          => false,
            'selected'         => false,
            'name'             => '',
            'id'               => '',
            'class'            => '',
            'show_option_none' => __( 'Choose an option', 'woocommerce' ),
        ) );

        $options               = $args['options'];
        $product               = $args['product'];
        $attribute             = $args['attribute'];
        $name                  = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
        $id                    = $args['id'] ? $args['id'] : sanitize_title( $attribute );
        $class                 = $args['class'];
        $show_option_none      = $args['show_option_none'] ? true : false;
        $show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' ); // We'll do our best to hide the placeholder, but we'll need to show something when resetting options.

        if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
            $attributes = $product->get_variation_attributes();
            $options    = $attributes[ $attribute ];
        }

        $html = '';
        $html .= '' . esc_html( $show_option_none_text ) . '';

        if ( ! empty( $options ) ) {
            if ( $product && taxonomy_exists( $attribute ) ) {
                // Get terms if this is a taxonomy - ordered. We need the names too.
                $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );



                foreach ( $terms as $term ) {
                    if ( in_array( $term->slug, $options ) ) {
                        $html .= 'slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . ' ';
                    }
                }
            } else {
                foreach ( $options as $option ) {
                    // This handles lt 2.4.0 bw compatibility where text attributes were not sanitized.
                    $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );

                    $html .= '' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '  Output Stock Details Here ';
                }
            }
        }

        $html .= '';

        echo apply_filters( 'woocommerce_dropdown_variation_attribute_options_html', $html, $args );
    }
}

I can pull out the stock level for the overall product, but now for each variation.我可以提取整个产品的库存水平,但现在为每个变体。

Any help would be greatly appreciated.任何帮助将不胜感激。

Update 2021 (Only for variable products with 1 dropdown ) - thanks to @Alex Banks 2021 年更新(仅适用于具有1 个下拉菜单的可变产品)- 感谢 @Alex Banks

Anyway this will really work when there is ONLY ONE dropdown select field (so one attribute for the variations).无论如何,当只有一个下拉选择字段时这将真正起作用(因此变体的一个属性)。

With multiple attributes (so multiple dropdown select fields) it displays something that can be wrong depending on the variations stock status attributes terms combination.使用多个属性(因此有多个下拉选择字段),它会根据库存状态属性术语组合的变化显示一些可能出错的内容

See the screenshot at the end that shows a wrong display case…请参阅最后显示错误展示柜的屏幕截图……

I have tried the code of Ali_k , but it was not working in my test server when variable products have multiple dropdowns.我已经尝试了Ali_k的代码,但是当变量产品有多个下拉列表时,它在我的测试服务器中不起作用

So I have made some changes to the Ali_k 's code to get this working in my test server (with last WooCommerce version) .因此,我对Ali_k的代码进行了一些更改,以使其在我的测试服务器中运行(使用最新的 WooCommerce 版本)

To handle backorders see: Add backorders stock status to Woocommerce variable product dropdown要处理延期交货,请参阅: 将延期交货库存状态添加到 Woocommerce 变量产品下拉列表

The code:代码:

// Function that will check the stock status and display the corresponding additional text
function get_stock_status_text( $product, $name, $term_slug ){
    foreach ( $product->get_available_variations() as $variation ){
        if($variation['attributes'][$name] == $term_slug ) {
            $stock = $variation['is_in_stock'];
            break;
        }
    }
    return $stock == 1 ? ' - (In Stock)' : ' - (Out of Stock)';
}

// The hooked function that will add the stock status to the dropdown options elements.
add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'show_stock_status_in_dropdown', 10, 2);
function show_stock_status_in_dropdown( $html, $args ) {
    // Only if there is a unique variation attribute (one dropdown)
    if( sizeof($args['product']->get_variation_attributes()) == 1 ) :

    $options               = $args['options'];
    $product               = $args['product'];
    $attribute             = $args['attribute']; // The product attribute taxonomy
    $name                  = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
    $id                    = $args['id'] ? $args['id'] : sanitize_title( $attribute );
    $class                 = $args['class'];
    $show_option_none      = $args['show_option_none'] ? true : false;
    $show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' );

    if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
        $attributes = $product->get_variation_attributes();
        $options    = $attributes[ $attribute ];
    }

    $html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
    $html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>';

    if ( ! empty( $options ) ) {
        if ( $product && taxonomy_exists( $attribute ) ) {
            $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );

            foreach ( $terms as $term ) {
                if ( in_array( $term->slug, $options ) ) {
                    // HERE Added the function to get the text status
                    $stock_status = get_stock_status_text( $product, $name, $term->slug );
                    $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . $stock_status ) . '</option>';
                }
            }
        } else {
            foreach ( $options as $option ) {
                $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
                // HERE Added the function to get the text status
                $stock_status = get_stock_status_text( $product, $name, $option );
                $html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) . $stock_status ) . '</option>';
            }
        }
    }
    $html .= '</select>';

    endif;

    return $html;
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.代码位于活动子主题(或主题)的 function.php 文件或任何插件文件中。

Tested and work in variable products that have only one attribute for variations只有一个变体属性的可变产品中进行测试和工作……

在此处输入图片说明


With the code of Ali_K, Here an example of a wrong displayed text for a variable product with multiple select fields (so multiple attributes for variations) :使用 Ali_K 的代码,这里有一个带有多个选择字段的变量产品的错误显示文本示例(变体的多个属性)

在此处输入图片说明

Ok, first you'll need to get product variations like this:好的,首先你需要得到这样的产品变体:

$variations = $product->get_available_variations();

And inside options loop, you need to loop through the variations and find the current option stock status在期权循环中,您需要遍历变化并找到当前的期权库存状态

foreach ($variations as $variation) {
    if($variation['attributes'][$name] == $option) {
        $stock = $variation['is_in_stock'];

    }
}

Outside the variations loop you need to add the wording for in-stock and out-of-stock variations在变体循环之外,您需要添加库存和缺货变体的措辞

if( $stock == 1) {
    $stock_content = ' - In stock';
} else {
    $stock_content = ' - Out of stock';
}

Then change the html to include an additional variable ($stock_content)然后更改 html 以包含一个附加变量 ($stock_content)

$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( $option  .  $stock_content ) . '</option>'; 

So a complete function will look like this:所以一个完整的函数看起来像这样:

add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'show_stock_status_in_dropdown', 10, 2);
function show_stock_status_in_dropdown( $html, $args ) {
    $options = $args['options']; 
    $product = $args['product']; 
    $attribute = $args['attribute']; 
    $name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute ); 
    $id = $args['id'] ? $args['id'] : sanitize_title( $attribute ); 
    $class = $args['class']; 
    $show_option_none = $args['show_option_none'] ? true : false; 
    $show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' ); 

  // Get all product variations
    $variations = $product->get_available_variations();

    if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) { 
        $attributes = $product->get_variation_attributes(); 
        $options = $attributes[ $attribute ]; 
    } 

    $html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">'; 
    $html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>'; 

    if ( ! empty( $options ) ) { 
        if ( $product && taxonomy_exists( $attribute ) ) { 
          // Get terms if this is a taxonomy - ordered. We need the names too. 
          $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) ); 

          foreach ( $terms as $term ) { 
                if ( in_array( $term->slug, $options ) ) { 
                    $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</option>'; 
                } 
            }
        } else {
            foreach ( $options as $option ) {
                    foreach ($variations as $variation) {
                        if($variation['attributes'][$name] == $option) {
                            $stock = $variation['is_in_stock'];
                        }
                    }       
                if( $stock == 1) {
                    $stock_content = ' - (In Stock)';
                } else {
                    $stock_content = ' - (Out of Stock)';
                }
                 // This handles < 2.4.0 bw compatibility where text attributes were not sanitized. 
                $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false ); 

                $html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( $option  .  $stock_content ) . '</option>'; 

            }
        } 
    } 

    $html .= '</select>'; 

    return $html;
}

@LoicTheAztec @LoicTheAztec

I have been using your updated code with the backorder function replacement too but come across an error due to a non-existent function call.我也一直在使用您更新的代码和延期交货函数替换,但由于不存在的函数调用而遇到错误。

get_the_stock_status() is now get_stock_status() is it not ? get_the_stock_status()现在是get_stock_status()不是吗?

Anyhow, the updated code below fixes the issue and an issue I had with a gift card plugin that was failing to load due to the above error.无论如何,下面的更新代码解决了这个问题以及我遇到的一个由于上述错误而无法加载的礼品卡插件的问题。

// Function that will check the stock status and display the corresponding additional text
function get_stock_status_text( $product, $name, $term_slug ){
    foreach ( $product->get_available_variations() as $variation ){
        if($variation['attributes'][$name] == $term_slug ) {
            $is_in_stock = $variation['is_in_stock'];
            $backordered = get_post_meta( $variation['variation_id'], '_backorders', true );
            $stock_qty   = get_post_meta( $variation['variation_id'], '_stock', true );
            break;
        }
    }
    $stock_status_text = $is_in_stock == 1 ? ' - (In Stock)' : ' - (Out of Stock)';
    return $backordered !== 'no' && $stock_qty <= 0 ? ' - (On Backorder)' : $stock_status_text;
}

// The hooked function that will add the stock status to the dropdown options elements.
add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'show_stock_status_in_dropdown', 10, 2);
function show_stock_status_in_dropdown( $html, $args ) {

    // Only if there is a unique variation attribute (one dropdown)
    if( sizeof($args['product']->get_variation_attributes()) == 1 ) :

    $options               = $args['options'];
    $product               = $args['product'];
    $attribute             = $args['attribute']; // The product attribute taxonomy
    $name                  = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
    $id                    = $args['id'] ? $args['id'] : sanitize_title( $attribute );
    $class                 = $args['class'];
    $show_option_none      = $args['show_option_none'] ? true : false;
    $show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' );

    if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
        $attributes = $product->get_variation_attributes();
        $options    = $attributes[ $attribute ];
    }

    $html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
    $html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>';

    if ( ! empty( $options ) ) {
        if ( $product && taxonomy_exists( $attribute ) ) {
            $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );

            foreach ( $terms as $term ) {
                if ( in_array( $term->slug, $options ) ) {
                    // HERE Added the function to get the text status
                    $stock_status = get_stock_status_text( $product, $name, $term->slug );
                    $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . $stock_status ) . '</option>';
                }
            }
        } else {
            foreach ( $options as $option ) {
                $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
                // HERE Added the function to get the text status
                $stock_status = get_stock_status( $product, $name, $option );
                $html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) . $stock_status ) . '</option>';
            }
        }
    }
    $html .= '</select>';

    endif;

    return $html;
}

I adapted your code so that only in stock variations display in the dropdown.我调整了您的代码,以便仅在下拉列表中显示库存变化。 I made $stock return bool, then我做了 $stock return bool,然后

if ($stock_status){
            $html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) /*. $stock_status*/ ) . '</option>';
            }

If you can think of a better way to do this It would be much appreciated.如果您能想到更好的方法来做到这一点,将不胜感激。 PS thank you for this solution, I can't believe this isn't default woocommerce behaviour to hide out of stock variants. PS 感谢您提供此解决方案,我不敢相信这不是隐藏缺货变体的默认 woocommerce 行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM