HomeChưa phân loạiHướng dẫn lập trình bộ lọc sản phẩm đa năng cho WooCommerce từ A-Z

Hướng dẫn lập trình bộ lọc sản phẩm đa năng cho WooCommerce từ A-Z

Bước 1: Các bạn tạo shortcode để hiển thị bộ lọc:

function custom_sidebar_product_filter() {
    // 1. Lấy dữ liệu hiện tại từ URL để đánh dấu trạng thái "Active"
    $current_cat   = isset($_GET['f_cat']) ? $_GET['f_cat'] : '';
    $current_color = isset($_GET['f_color']) ? $_GET['f_color'] : '';
    $current_size  = isset($_GET['f_size']) ? $_GET['f_size'] : '';
    $current_price = isset($_GET['f_price']) ? $_GET['f_price'] : '';
    // Xử lý giá min/max từ URL
    $min_price = isset($_GET['min_price']) ? intval($_GET['min_price']) : 0;
    $max_price = isset($_GET['max_price']) ? intval($_GET['max_price']) : 100000; // Giá tối đa mặc định

    // Hàm hỗ trợ tạo link lọc nhanh
    function get_filter_link($param, $value) {
        $link = strtok($_SERVER["REQUEST_URI"], '?');
        $query = $_GET;
        // $query = [
        //     "f_cat" => "clothing",
        // ];
        if ($value) {
            $query[$param] = $value;
        } else {
            unset($query[$param]);
        }
        // Giữ lại các tham số lọc khác khi nhấn vào một lọc mới
        return add_query_arg($query, $link);
    }

    ob_start(); ?>
    <div class="col-lg-3">
        <div class="shop-sidebar-style">
            
            <div class="sidebar-widget">
                <h4 class="pro-sidebar-title">Categories</h4>
                <div class="sidebar-widget-categori mt-45 mb-70">
                    <ul>
                        <li><a href="<?php echo get_filter_link('f_cat', ''); ?>">All</a></li>
                        <?php
                        $categories = get_terms('product_cat', array('hide_empty' => true));
                        foreach ($categories as $cat) :
                            $active = ($current_cat == $cat->slug) ? 'active' : '';
                            echo '<li><a class="'.$active.'" href="'.get_filter_link('f_cat', $cat->slug).'">'.$cat->name.'</a></li>';
                        endforeach; ?>
                    </ul>
                </div>
            </div>

            <div class="sidebar-widget">
                <h4 class="pro-sidebar-title">Filter By Color</h4>
                <div class="pro-details-color-content sidebar-widget-color mt-45 mb-70">
                    <ul>
                        <?php
                        $colors = get_terms('pa_color', array('hide_empty' => true));
                        foreach ($colors as $color) :
                            $active = ($current_color == $color->slug) ? 'active' : '';
                            echo '<li><a class="'.$color->slug.' '.$active.'" href="'.get_filter_link('f_color', $color->slug).'">'.'</a></li>';
                        endforeach; ?>
                    </ul>
                </div>
            </div>

            <div class="sidebar-widget">
                <h4 class="pro-sidebar-title">Filter By Price Range</h4>
                <div class="price-filter mt-55 mb-65">
                    <div id="slider-range"></div>
                    <div class="price-slider-amount">
                        <div class="label-input">
                            <span>Price: </span>
                            <input type="text" id="amount" name="price" readonly placeholder="Add Your Price" />
                        </div>
                        <form id="price-filter-form" method="GET" action="<?php echo strtok($_SERVER["REQUEST_URI"], '?'); ?>">
                            <?php if($current_cat): ?><input type="hidden" name="f_cat" value="<?php echo $current_cat; ?>"><?php endif; ?>
                            <?php if($current_color): ?><input type="hidden" name="f_color" value="<?php echo $current_color; ?>"><?php endif; ?>
                            <?php if($current_size): ?><input type="hidden" name="f_size" value="<?php echo $current_size; ?>"><?php endif; ?>
                            
                            <input type="hidden" id="min_price" name="min_price" value="<?php echo $min_price; ?>">
                            <input type="hidden" id="max_price" name="max_price" value="<?php echo $max_price; ?>">
                            <button type="submit" class="btn-filter" style="margin-top:15px; background:#333; color:#fff; border:none; padding:5px 15px; cursor:pointer;">Filter Now</button>
                        </form>
                    </div>
                </div>
            </div>

        </div>
    </div>
   

    
    <?php
    return ob_get_clean();
}
add_shortcode('custom_sidebar_filter', 'custom_sidebar_product_filter');

Bước 2: Dán shortcode này vào trong template archive để hiển thị ra giao diện:

<?php echo do_shortcode('[custom_sidebar_filter]'); ?>

Bước 3: Xây dựng câu truy vấn query cho shortcode mặc định hiển thị sản phẩm của Woocommerce:

add_action( 'woocommerce_product_query', 'custom_force_product_filter_logic', 999 );

function custom_force_product_filter_logic( $query ) {
    if ( is_admin() ) return;

    // Lấy các giá trị từ URL
    $min = isset($_GET['min_price']) ? intval($_GET['min_price']) : '';
    $max = isset($_GET['max_price']) ? intval($_GET['max_price']) : '';
    
    $f_cat = isset($_GET['f_cat']) ? sanitize_text_field($_GET['f_cat']) : '';
    $f_color = isset($_GET['f_color']) ? sanitize_text_field($_GET['f_color']) : '';
    $f_size = isset($_GET['f_size']) ? sanitize_text_field($_GET['f_size']) : '';

    $meta_query = (array) $query->get( 'meta_query' );
    $tax_query  = (array) $query->get( 'tax_query' );

    

    // 1. ÉP LỌC GIÁ (Cách này can thiệp sâu vào tầng meta của Woo)
    if ( $min !== '' && $max !== '' ) {
        $meta_query[] = array(
            'key'     => '_price',
            'value'   => array( $min, $max ),
            'compare' => 'BETWEEN',
            'type'    => 'NUMERIC',
        );
    }

    // 2. ÉP LỌC CHUYÊN MỤC
    if ( ! empty( $f_cat ) ) {
        $tax_query[] = array(
            'taxonomy' => 'product_cat',
            'field'    => 'slug',
            'terms'    => $f_cat,
            'operator' => 'IN',
        );
    }

    // 3. ÉP LỌC THUỘC TÍNH (Màu sắc & Kích thước)
    if ( ! empty( $f_color ) ) {
        $tax_query[] = array(
            'taxonomy' => 'pa_color',
            'field'    => 'slug',
            'terms'    => $f_color,
            'operator' => 'IN',
        );
    }
    
    if ( ! empty( $f_size ) ) {
        $tax_query[] = array(
            'taxonomy' => 'pa_size',
            'field'    => 'slug',
            'terms'    => $f_size,
            'operator' => 'IN',
        );
    }

    $query->set( 'meta_query', $meta_query );
    $query->set( 'tax_query', $tax_query );
}

*Lưu ý, chèn thêm đoạn code này nếu bạn sử dụng thư viện jquery-ui cho tính năng price range:

add_action('wp_footer', function() {
    ?>
    <script type="text/javascript">
    (function($) {
        "use strict";
        
        // Hàm kiểm tra định kỳ xem thư viện đã sẵn sàng chưa
        var checkSliderLibrary = setInterval(function() {
            if ($.isFunction($.fn.slider)) {
                clearInterval(checkSliderLibrary); // Dừng kiểm tra khi đã thấy thư viện
                
                var minVal = parseInt($("#min_price").val()) || 0;
                var maxVal = parseInt($("#max_price").val()) || 100000;

                $("#slider-range").slider({
                    range: true,
                    min: 0,
                    max: 100000,
                    values: [minVal, maxVal],
                    slide: function(event, ui) {
                        $("#amount").val(ui.values[0].toLocaleString() + "đ - " + ui.values[1].toLocaleString() + "đ");
                        $("#min_price").val(ui.values[0]);
                        $("#max_price").val(ui.values[1]);
                    }
                });
                
                $("#amount").val($("#slider-range").slider("values", 0).toLocaleString('vi-VN') + "đ - " + $("#slider-range").slider("values", 1).toLocaleString("vi-VN") + "đ");
                console.log("Slider initialized successfully!");
            }
        }, 100); // Kiểm tra mỗi 0.1 giây

    })(jQuery);
    </script>
    <?php
}, 999);

Chúc các bạn thực hành thành công!

Share:

You May Also Like

Trong video này, bạn sẽ học cách lập trình tính năng thêm vào giỏ hàng ngay trên Quick View modal...
Chào các bạn, đã rất lâu rồi mình mới sắp xếp được thời gian hướng dẫn cho mọi người tiếp...
Thông thường, khi đăng ký Custom Post Type (CPT), chúng ta hay viết các hàm rời rạc trong file functions.php....