phpwoocommerceproductshortcodetaxonomy-terms

Filter WooCommerce products from brand and category custom dropdowns


I'm trying to create 2 dropdowns, one for brands from Perfect Brands for WooCommerce plugin, and the other for 2nd level product categories. The category works on it own, but the brands just returns the shop page with all the products. I looked up the taxonomy for Perfect Brands for WooCommerce plugin and I believe it is pwb-brand, which is the only one that has actually listed the brands in the dropdown. I need the dropdown to exclude products if both inputs are selected, clearly, but as of now only categories works.

Here is my code:

// Dropdown Function
function woocommerce_category_dropdown() {
    // Get all product categories excluding "ALL" and second-level categories
    $args = array(
        'taxonomy' => 'product_cat',
        'orderby' => 'name',
        'order'   => 'ASC',
        'hide_empty' => false,
    );
    $categories = get_terms($args);

    // Get all brands using Perfect Brands WooCommerce plugin
    $brands = get_terms(array(
        'taxonomy' => 'pwb-brand',
        'orderby' => 'name',
        'order'   => 'ASC',
        'hide_empty' => false,
    ));

    // Start output buffering
    ob_start();
    ?>

    <form role="search" method="get" id="categorysearchform" action="<?php echo esc_url(home_url('/')); ?>">
        <!-- Brand dropdown -->
        <select name="brand" id="brand">
            <option value=""><?php _e('Elige una marca', 'woocommerce'); ?></option>
            <?php foreach ($brands as $brand) : ?>
                <option value="<?php echo esc_attr($brand->slug); ?>"><?php echo esc_html($brand->name); ?></option>
            <?php endforeach; ?>
        </select>

        <!-- Second-level category dropdown excluding "ALL" -->
        <select name="product_cat" id="product_cat">
            <option value=""><?php _e('Elige una categoría', 'woocommerce'); ?></option>
            <?php foreach ($categories as $category) : ?>
                <?php
                // Skip the "ALL" category
                if ($category->name === 'ALL') {
                    continue;
                }

                // Get second-level categories
                if ($category->parent != 0) {
                    $parent = get_term($category->parent, 'product_cat');
                    if ($parent->parent == 0) { // Only show second-level categories
                        $parent_category = $category->name; // Remove arrow symbol
                        ?>
                        <option value="<?php echo esc_attr($category->slug); ?>"><?php echo esc_html($parent_category); ?></option>
                        <?php
                    }
                }
                ?>
            <?php endforeach; ?>
        </select>

        <input type="hidden" value="product" name="post_type" />
        <button type="submit" id="searchsubmit"><?php _e('Buscar', 'woocommerce'); ?></button>
    </form>

    <?php
    // Return the output
    return ob_get_clean();
}

add_shortcode('woocommerce_category_dropdown', 'woocommerce_category_dropdown');

Solution

  • The main issue in your code is that you need to add the Brands taxonomy "pwb-brand" as attribute name on your related <select> field.

    I have revisited your code:

    add_shortcode('brand_category_filter', 'filter_products_from_brand_and_category_dropdowns');
    function filter_products_from_brand_and_category_dropdowns() {
        // Get all product categories excluding "ALL" and second-level categories
        $categories = get_terms( array(
            'taxonomy' => 'product_cat',
            'orderby' => 'name',
            'order'   => 'ASC',
            'hide_empty' => false,
        ) );
    
        // Get all brands using Perfect Brands WooCommerce plugin
        $brands = get_terms( array(
            'taxonomy' => 'pwb-brand',
            'orderby' => 'name',
            'order'   => 'ASC',
            'hide_empty' => false,
        ) );
    
        ob_start(); // Start output buffering
        ?>
        <form role="search" method="get" id="categorysearchform" action="<?php echo esc_url(home_url('/')); ?>">
            <!-- Brand dropdown -->
            <select name="pwb-brand" id="pwb-brand">
                <option value=""><?php esc_html_e('Choose a brand', 'woocommerce'); ?></option>
                <?php // Loop through brands
                foreach ( $brands as $brand ) { 
                    printf('<option value="%s">%s</option>', esc_attr($brand->slug), esc_html($brand->name) );
                } ?>
            </select>
    
            <!-- Second-level category dropdown excluding "ALL" -->
            <select name="product_cat" id="product_cat">
                <option value=""><?php _e('Choose a category', 'woocommerce'); ?></option>
                <?php // Loop through categories
                foreach ( $categories as $category ) {
                    // Skip the "ALL" category
                    if ($category->name === 'ALL') {
                        continue;
                    }
                    // Get second-level categories
                    if ($category->parent != 0) {
                        $parent = get_term($category->parent, 'product_cat');
                        if ($parent->parent == 0) { // Only show second-level categories
                            printf('<option value="%s">%s</option>', esc_attr($category->slug), esc_html($category->name) );
                        }
                    }
                } ?>
            </select>
            <input type="hidden" value="product" name="post_type" />
            <button type="submit" id="searchsubmit"><?php _e('Search', 'woocommerce'); ?></button>
        </form>
        <?php
        // Return the output
        return ob_get_clean();
    }
    

    Shortcode usage: [brand_category_filter]

    Code goes in functions.php file of your child theme (or in a plugin). It should better work.