【问题标题】:woocommerce widget "filter products by attribute" displays unavailable productswoocommerce 小部件“按属性过滤产品”显示不可用的产品
【发布时间】:2021-01-17 22:02:38
【问题描述】:

我正在使用Widgets included with WooCommerce 中的一个,称为Filter products by attribute。我在我的 Storefront-child-theme functions.php 的类别页面上创建了一个小部件区域(参见下面的代码)。

但是,例如,当我按属性size M 进行过滤时,它会列出尺寸 M 缺货的产品...

知道如何解决这个问题吗?

示例:按尺寸 M 过滤显示此产品,该产品不可用:

/* FILTER BY SIZE WIDGET */
// Adding the widget area.
if (function_exists('register_sidebar')) {
    register_sidebar(array(
    'name' => 'Below category title',
    'id' => 'extra-widget-area',
    'description' => 'Below category title',
    'before_widget' => '<div class="widget below-cat-title-widget">',
    'after_widget' => '</div>',
    'before_title' => '<h6 class="below-cat-title-widget-title">',
    'after_title' => '</h6>'
    ));
}
// placing the widget
add_action( 'woocommerce_archive_description', 'add_my_widget_area', 31 );
function add_my_widget_area() {
  if (function_exists('dynamic_sidebar')) {
    dynamic_sidebar('Below category title');
  }
}

add_action( 'woocommerce_archive_description', 'filter_button_function', 21 );
function filter_button_function() {
    // if ( is_product_category() ) {
        // global $wp_query;
        // $cat_id = $wp_query->get_queried_object_id();
        // $cat_desc = term_description( $cat_id, 'product_cat' );
        if (get_locale() == 'fr_FR') {
            $filter_html = '<div class="filter_by_size" class="subtitle">'.'FILTRE PAR TAILLE'.'&nbsp;&nbsp;<span class="filter-icon"></span>'.'</div>';
        } else {
            $filter_html = '<div class="filter_by_size" class="subtitle">'.'FILTER BY SIZE'.'&nbsp;&nbsp;<span class="filter-icon"></span>'.'</div>';
        }

        echo $filter_html;
    // }
}

【问题讨论】:

    标签: php html jquery wordpress woocommerce


    【解决方案1】:

    我会直接:默认情况下,you can't。它与某个主题或插件无关,而是与 Woocommerce 本身有关。这是 woocommerce for a very long time 中存在的问题。默认情况下,woocommerce 无法根据其变体可见性处理可变产品库存可见性(库存状态),因为这是 Woocommerce 必需和需要的东西1

    一种方法是添加这个动作函数:

    add_action('woocommerce_before_shop_loop_item', 'out_of_stock_variations_loop');
    function out_of_stock_variations_loop()
    {
        global $product;
        $filter = 'size';
        if ($product->product_type === 'variable') {
            $available = $product->get_available_variations();
            if ($available) {
                foreach ($available as $instockvar) {
                    if (isset($instockvar[ 'attributes' ][ 'attribute_pa_' . $filter ])) {
                        if ($_GET[ 'filter_' . $filter ]) {
                            if ( !in_array( $instockvar[ 'attributes' ][ 'attribute_pa_' . $filter ], explode(',', $_GET[ 'filter_' . $filter ]) , true ) || ($instockvar[ 'max_qty' ] <= 0) ) {
                                echo "<style>.post-" . $product->get_id() . " {display: none}</style>";
                            } else {
                                echo "<style>.post-" . $product->get_id() . " {display: list-item !important}</style>";
                            }
                        }
                    }
                }
            }
        }
    }
    ?>
    

    这只会显示库存产品列表。这样做的问题是,它将在此查询删除非库存产品的位置留下空白,并且仅使用 css 很难规避此问题,因为在每一行上,第一个和最后一个产品都有 @987654330 @ 和 last 类确定它们在 CSS 中的布局。为了克服这个问题,将此 jQuery 添加到您的子主题 js 脚本中:

    function openLayeredNavFilterIfSelected() {
    
      if (jQuery('.wc-layered-nav-term').hasClass('woocommerce-widget-layered-nav-list__item--chosen')) {
    
        /*keep layered nav filter open, if at least an attribute is selected*/
        jQuery('.woocommerce-widget-layered-nav-list__item--chosen').parent().parent().show();
        if (!jQuery('.filter-icon').hasClass('arrow_up')) {
          jQuery('.filter-icon').addClass('arrow_up');
        }
    
        /*redistribute products rows to avoid missing spaces*/
        jQuery('.site-main ul.products.columns-3 li.product').removeClass('first').removeClass('last');
        jQuery('.site-main ul.products.columns-3 li.product:visible').each(function(i) {
          if (i % 3 == 0) jQuery(this).addClass('first'); //add class first to firsts products of rows
          if (i % 3 == 2) jQuery(this).addClass('last'); //add class last to lasts products of rows
        });
      }
    }
    
    openLayeredNavFilterIfSelected();
    jQuery(window).resize(openLayeredNavFilterIfSelected);
    

    你应该很高兴。

    1WOOF Products Filter plugin and out of stock variations issue in Woocommerce

    相关:

    -filter products by attribute and hide out of stock items of variable products

    -How to prevent `out of stock` items to show as a filter option in the sidebar (layered nav widget ) in WooCommerce?

    -https://wordpress.org/support/topic/hide-out-of-stock-variations-when-filtering/#post-7718128

    -https://xtemos.com/forums/topic/filter-attributes-dont-show-out-of-stock-variations/

    -https://wordpress.org/support/topic/exclude-out-of-stock-products-from-filter/

    【讨论】:

      【解决方案2】:

      这里不是一个很好的答案。

      正如@Islam Elshobokshy 所说,编辑产品循环查询以删除缺货变化有点复杂。

      不过,您仍然可以欺骗使用 CSS 从列表中“隐藏”缺货变体。但这可能会“破坏”您的产品列表/网格:如果有足够的产品用于 2 页(10 件/页),但此过滤器在第 1 页上隐藏了一个产品,则第 1 页将只有 9 个产品。我们正在查询产品。

      我很快测试并写了一些受this启发的东西:

      • 这适用于 size 属性(它可以适用于处理来自 Woocommerce 的所有属性,或 URL 参数“filter_*”,或对使用的每个属性进行硬编码)

      代码:

      add_action('woocommerce_before_shop_loop_item', 'out_of_stock_variations_loop');
      function out_of_stock_variations_loop()
      {
          global $product;
      
          $filter = 'size'; //to edit
      
          if ($product->product_type === 'variable') {
              $available = $product->get_available_variations();
              if ($available) {
                  foreach ($available as $instockvar) {
                      if (isset($instockvar[ 'attributes' ][ 'attribute_pa_' . $filter ])) {
                          if (($instockvar[ 'attributes' ][ 'attribute_pa_' . $filter ] === $_GET[ 'filter_' . $filter ]) && ($instockvar[ 'max_qty' ] <= 0)) {
                              //sadly echo some inline CSS :(
                              echo "<style>.post-" . $product->get_id() . " {display: none}</style>";
      
                              //some tests using is_visible() filters, but we are too late here
                              //add_filter( 'woocommerce_product_is_visible', function($visible, $id) use ($the_id) {return $id === $the_id ? false : $visible;}, 50, 2);
                          }
                      }
                  }
              }
          }
      }
      

      要在不使用内联 CSS 的情况下达到同样的效果,您可以:

      • /woocommerce/template/content-product.php 覆盖为your-theme/woocommerce/content-product.php
      • 将下面的代码移动到 method($product) 中,稍作修改以仅对所需产品返回 true/false
      • 在“确保可见性”块中调用它,例如 if ( empty( $product ) || ! $product-&gt;is_visible() || !$method($product) )
      • 这将阻止输出产品,但不会解决网格/列表问题。

      最后,根据您的需要更新循环查询可能会很复杂,并且会对性能产生负面影响。但是,为了探索更多,我会开始这样的事情:

      • 通过检测 GET 过滤器参数添加 query_var(或直接检测与您知道将过滤的过滤器/属性匹配的 wp_query 参数)
      • 查找并使用 woocommerce 产品 wp_query
      • 挂钩一个可以检测您的自定义 query_var 的方法
      • 编辑查询,但如果涉及到原始 SQL,可能会很痛苦..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-12
        • 2011-06-22
        • 1970-01-01
        • 2018-09-08
        相关资源
        最近更新 更多