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

How to add variation stock status to Woocommerce product variation dropdown

我想显示 Woocommerce 产品页面上变体下拉列表中显示的每个产品变体的库存状态(例如,有货/缺货)。我已将相关功能复制到我主题的 functions.php 文件中,并可以编辑内容,但不确定如何为每个变体提取所需的库存状态。


// 更新了 Woocommerce 产品变体 Select

如果(!function_exists('wc_dropdown_variation_attribute_options')){

    /**
     * 输出用于购物车表单的变体属性列表。
     *
     * @param 数组 $args
     * @自 2.4.0 起
     */

     /*

    函数 wc_dropdown_variation_attribute_options( $args = array() ) {
        $args = wp_parse_args( apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ), array(
            'options' => 错误,
            'attribute' => 错误,
            'product' => 错误,
            'selected' => 错误,
            '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($属性);
        $id = $args['id'] ? $args['id'] : sanitize_title( $attribute );
        $class = $args['class'];
        $show_option_none = $args['show_option_none'] ?真假;
        $show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' ); // 我们会尽力隐藏占位符,但我们需要在重置选项时显示一些内容。

        如果(空($options)&&!空($product)&&!空($attribute)){
            $attributes = $product->get_variation_attributes();
            $options = $attributes[ $attribute ];
        }

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

        如果(!空($选项)){
            如果($product && taxonomy_exists($attribute)){
                // 如果这是分类法,则获取术语 - 有序。我们也需要名字。
                $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );



                foreach ( $terms 作为 $term ) {
                    如果 ( 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 ) ) . ' ';
                    }
                }
            } 别的 {
                foreach ( $options 作为 $option ) {
                    // 这处理 lt 2.4.0 bw 兼容性,其中文本属性未清理。
                    $selected = sanitize_title( $args['selected'] ) === $args['selected'] ?选择($args['selected'],sanitize_title($option),false):选择($args['selected'],$option,false);

                    $html .= '' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) 。 '在此处输出库存详情';
                }
            }
        }

        $html .= '';

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

我可以提取整个产品的库存水平,但现在是每个变体。

如有任何帮助,我们将不胜感激。

好的,首先您需要获得如下产品变体:

$variations = $product->get_available_variations();

在期权循环中,您需要遍历变量并找到当前的期权股票状态

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

然后更改 html 以包含一个附加变量 ($stock_content)

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

所以一个完整的函数应该是这样的:

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

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…

我已经尝试了 Ali_k 的代码,但是当可变产品有多个下拉菜单。

因此,我对 Ali_k 的代码进行了一些更改,以使其在我的测试服务器 (使用最新的 WooCommerce 版本)中运行.

要处理延期交货,请参阅:

代码:

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

代码进入您的活动子主题(或主题)的 function.php 文件或任何插件文件。

测试并使用可变产品只有一个变体属性


使用 Ali_K 的代码,这里是变量产品 具有多个 select 字段的错误显示文本示例 (所以变体有多个属性):

@LoicTheAztec

我也一直在使用您的更新代码和延期交货功能替换,但由于不存在的功能调用而遇到错误。

get_the_stock_status() 现在是 get_stock_status() 不是吗?

无论如何,下面更新的代码解决了这个问题以及我遇到的由于上述错误而无法加载的礼品卡插件问题。

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

我调整了您的代码,以便仅在库存变化中显示在下拉列表中。我将 $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>';
            }

如果您能想到更好的方法来做到这一点,将不胜感激。 P.S 感谢您提供此解决方案,我无法相信这不是隐藏缺货变体的默认 woocommerce 行为。