简体   繁体   中英

Remove categories from widget based on number of products

Since my shop has a lot of subcategories I'm trying to exclude all categories from my widget which only have 1 product inside.

Now I found following code to exclude cats by ID but this would be too time consuming to do in this case. Any suggestions on how to edit this code to exclude by post count?

    add_filter( 'woocommerce_product_categories_widget_args', 'wdm_edit_product_cat_widget_args' ); function wdm_edit_product_cat_widget_args( $cat_args ) {
$cat_args['exclude'] = array('10387');
return $cat_args;}

One fun way I thought about was to use your custom made Walker for listing the categories. There you have some options, including:

  1. You can check if a certain item has 1 products, then you can add a conditional tag and prevent it from showing up.

  2. You can add the count of products in that item in the li class and using css hide items with certain classes (.cat-count-1) in your case.

I personally like the second way because it allows you to do whatever you want with items later.

Here is how it works:

1- Add this piece of code in your theme's functions.php file:

add_filter('woocommerce_product_categories_widget_args', 'use_different_walker_with_counts');
function use_different_walker_with_counts($args){
  include_once 'wc_walker_with_counter_class.php';
  $args['walker'] = new WC_Product_Cat_List_Counter_Walker;
  return $args;
}

this tells wordpress to use another custom made walker.

2- Add a new file in your theme folder name wc_walker_with_counter_class.php with these lines:

<?php


class WC_Product_Cat_List_Counter_Walker extends Walker {

    /**
     * What the class handles.
     *
     * @var string
     */
    public $tree_type = 'product_cat';

    /**
     * DB fields to use.
     *
     * @var array
     */
    public $db_fields = array(
        'parent' => 'parent',
        'id'     => 'term_id',
        'slug'   => 'slug'
    );

    /**
     * Starts the list before the elements are added.
     *
     * @see Walker::start_lvl()
     * @since 2.1.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int $depth Depth of category. Used for tab indentation.
     * @param array $args Will only append content if style argument value is 'list'.
     */
    public function start_lvl( &$output, $depth = 0, $args = array() ) {
        if ( 'list' != $args['style'] )
            return;

        $indent = str_repeat("\t", $depth);
        $output .= "$indent<ul class='children'>\n";
    }

    /**
     * Ends the list of after the elements are added.
     *
     * @see Walker::end_lvl()
     * @since 2.1.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int $depth Depth of category. Used for tab indentation.
     * @param array $args Will only append content if style argument value is 'list'.
     */
    public function end_lvl( &$output, $depth = 0, $args = array() ) {
        if ( 'list' != $args['style'] )
            return;

        $indent = str_repeat("\t", $depth);
        $output .= "$indent</ul>\n";
    }

    /**
     * Start the element output.
     *
     * @see Walker::start_el()
     * @since 2.1.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int $depth Depth of category in reference to parents.
     * @param integer $current_object_id
     */
    public function start_el( &$output, $cat, $depth = 0, $args = array(), $current_object_id = 0 ) {
        $output .= '<li class="cat-item cat-item-' . $cat->term_id . ' cat-count-' . $cat->count;

        if ( $args['current_category'] == $cat->term_id ) {
            $output .= ' current-cat';
        }

        if ( $args['has_children'] && $args['hierarchical'] ) {
            $output .= ' cat-parent';
        }

        if ( $args['current_category_ancestors'] && $args['current_category'] && in_array( $cat->term_id, $args['current_category_ancestors'] ) ) {
            $output .= ' current-cat-parent';
        }

        $output .=  '"><a href="' . get_term_link( (int) $cat->term_id, $this->tree_type ) . '">' . _x( $cat->name, 'product category name', 'woocommerce' ) . '</a>';

        if ( $args['show_count'] ) {
            $output .= ' <span class="count">(' . $cat->count . ')</span>';
        }
    }

    /**
     * Ends the element output, if needed.
     *
     * @see Walker::end_el()
     * @since 2.1.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param int $depth Depth of category. Not used.
     * @param array $args Only uses 'list' for whether should append to output.
     */
    public function end_el( &$output, $cat, $depth = 0, $args = array() ) {
        $output .= "</li>\n";
    }

    /**
     * Traverse elements to create list from elements.
     *
     * Display one element if the element doesn't have any children otherwise,
     * display the element and its children. Will only traverse up to the max.
     * depth and no ignore elements under that depth. It is possible to set the.
     * max depth to include all depths, see walk() method.
     *
     * This method shouldn't be called directly, use the walk() method instead.
     *
     * @since 2.5.0
     *
     * @param object $element Data object
     * @param array $children_elements List of elements to continue traversing.
     * @param int $max_depth Max depth to traverse.
     * @param int $depth Depth of current element.
     * @param array $args
     * @param string $output Passed by reference. Used to append additional content.
     * @return null Null on failure with no changes to parameters.
     */
    public function display_element( $element, &$children_elements, $max_depth, $depth = 0, $args, &$output ) {
        if ( ! $element || ( 0 === $element->count && ! empty( $args[0]['hide_empty'] ) ) ) {
            return;
        }
        parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }
}

3- Then you can go ahead and do what you want in your styles file, usually style.css . In this case we want to hide items with count of one so we add:

.cat-count-1 {
    display: none;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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