Sắp xếp thứ tự theo ngày tháng khi dùng nhiều danh mục con

Woocommerce Sap xep thu tu theo ngay thang khi dung nhieu danh muc con

Vấn đề sắp xếp sản phẩm khi dùng nhiều danh mục con trong WooCommerce

Khi làm website WooCommerce, việc tổ chức sản phẩm theo danh mục cha và danh mục con là rất phổ biến. Ví dụ: danh mục “Điện thoại” có các danh mục con như “Samsung”, “Apple”, “Xiaomi”, v.v. Khi người dùng nhấp vào danh mục cha “Điện thoại”, họ mong muốn thấy tất cả sản phẩm từ các danh mục con được hiển thị và sắp xếp theo một logic hợp lý, thường là theo ngày tháng mới nhất.

Tuy nhiên, WooCommerce có một hành vi mặc định khá khó chịu: khi bạn truy cập vào một danh mục cha có nhiều danh mục con, thay vì sắp xếp sản phẩm theo ngày đăng hay giá, nó sẽ lấy sản phẩm theo thứ tự của danh mục con. Nghĩa là sản phẩm từ danh mục con đầu tiên hiển thị hết, rồi mới đến danh mục con thứ hai, và tiếp tục như vậy.

Sắp xếp thứ tự theo ngày tháng khi dùng nhiều danh mục con  -  minh hoạ vấn đề

Hình trên minh hoạ rõ vấn đề. Các sản phẩm không được sắp xếp theo thứ tự thời gian mà theo thứ tự danh mục con. Điều này khiến trang danh mục nhìn rất lộn xộn, đặc biệt khi mỗi danh mục con có sản phẩm được đăng vào các ngày khác nhau. Người dùng khó tìm được sản phẩm mới nhất nếu nó nằm ở danh mục con cuối cùng.

Nguyên nhân WooCommerce hiển thị theo danh mục con

WooCommerce sử dụng WP_Query với tax_query để lấy sản phẩm từ danh mục cha bao gồm tất cả danh mục con. Tuy nhiên, truy vấn này không tự động group hay sort các kết quả theo ngày mà lấy theo thứ tự term ID của danh mục con. Hành vi này được quyết định bởi parameter orderby trong query, và giá trị mặc định thường không phải là date.

Để hiểu rõ hơn, WooCommerce page archive (trang danh mục sản phẩm) sử dụng template archive-product.php, bên trong gọi woocommerce_product_loop_start() và các hook liên quan. Truy vấn chính được filter qua hook woocommerce_get_catalog_ordering_args. Nếu bạn muốn thay đổi logic sort, đây là nơi cần can thiệp.

Giải pháp 1: Filter mặc định orderby thành date

Đây là giải pháp đơn giản và nhanh nhất. Bạn chỉ cần thêm đoạn code sau vào file functions.php của theme (hoặc child theme) để thay đổi cách sắp xếp mặc định của catalog.

// Thay đổi sắp xếp mặc định thành theo ngày tháng
add_filter('woocommerce_default_catalog_orderby',
    'custom_default_catalog_orderby');

function custom_default_catalog_orderby($sort_by) {
    return 'date';
}

Đoạn code này sử dụng filter woocommerce_default_catalog_orderby để thay đổi giá trị sort mặc định. Khi user truy cập trang danh mục mà chưa chọn thứ tự sắp xếp nào, WooCommerce sẽ dùng giá trị date thay vì giá trị mặc định (thường là popularity hoặc rating).

Lưu ý: Giải pháp này thay đổi mặc định cho TẤT CẢ các trang catalog, không chỉ riêng trang danh mục cha. Nếu bạn chỉ muốn áp dụng cho một số trang cụ thể, cần thêm điều kiện kiểm tra.

Giải pháp 2: Filter toàn bộ catalog ordering args

Nếu bạn cần kiểm soát nhiều hơn, bao gồm cả thứ tự sort (ASC/DESC), hãy dùng filter woocommerce_get_catalog_ordering_args:

// Sắp xếp catalog theo ngày tháng, mới nhất lên đầu
add_filter('woocommerce_get_catalog_ordering_args',
    'custom_catalog_ordering_args');

function custom_catalog_ordering_args($args) {
    $args['orderby'] = 'date';
    $args['order'] = 'DESC';
    return $args;
}

Đoạn code này set orderbydateorderDESC (mới nhất lên đầu). Phù hợp khi bạn muốn đảm bảo sản phẩm mới luôn hiển thị đầu tiên, bất kể thuộc danh mục con nào.

Giải pháp 3: Chỉ áp dụng cho danh mục cha

Nhiều trường hợp bạn chỉ muốn sắp xếp theo ngày ở trang danh mục cha, còn trang danh mục con vẫn giữ sắp xếp cũ (ví dụ sắp xếp theo popularity). Dùng hook pre_get_posts để can thiệp vào query:

// Sắp xếp theo ngày chỉ cho danh mục cha
add_action('pre_get_posts',
    'custom_sort_parent_category');

function custom_sort_parent_category($query) {
    // Chỉ áp dụng cho frontend product query
    if (!is_admin() && $query->is_main_query()
        && is_product_category()) {

        $term = get_queried_object();

        // Kiểm tra xem đây có phải danh mục cha
        // (có danh mục con) không
        $children = get_term_children(
            $term->term_id, 'product_cat'
        );

        if (!empty($children)) {
            $query->set('orderby', 'date');
            $query->set('order', 'DESC');
        }
    }
}

Đoạn code này kiểm tra xem term hiện tại có phải danh mục cha hay không (bằng cách kiểm tra xem nó có term children hay không). Nếu là danh mục cha, mới áp dụng sort theo ngày. Cách này linh hoạt hơn và không ảnh hưởng đến sắp xếp ở các trang khác.

Giải pháp 4: Chỉnh sửa qua WooCommerce Settings

Nếu bạn không muốn can thiệp vào code, WooCommerce có sẵn tùy chọn sắp xếp mặc định trong admin panel. Vào WooCommerce > Settings > Products > Display, tìm mục Default product sorting và chọn Sort by date (newest to oldest).

Cách này tương đương với Giải pháp 1 nhưng không cần code. Tuy nhiên, nó áp dụng toàn cục cho tất cả các trang shop. Nếu bạn cần logic phức tạp hơn (chỉ cho danh mục cha), vẫn phải dùng code.

Các tùy chọn sắp xếp phổ biến khác

Ngoài sắp xếp theo ngày, WooCommerce hỗ trợ nhiều cách sắp xếp khác mà bạn có thể áp dụng:

Sort by price: $args['orderby'] = 'price'; hoặc $args['meta_key'] = '_price'; $args['orderby'] = 'meta_value_num';. Phù hợp cho trang sale hoặc khuyến mãi.

Sort by popularity: return 'popularity';. WooCommerce tự động tính popularity dựa trên số lượng bán hàng. Đây là giá trị mặc định của nhiều theme.

Sort by rating: return 'rating';. Chỉ hoạt động khi bạn bật tính năng review trong WooCommerce.

Sort by title: $args['orderby'] = 'title';. Sắp xếp theo bảng chữ cái tên sản phẩm, hữu ích cho trang có nhiều sản phẩm cần tìm theo tên.

Sort by stock status: Custom sort để đưa sản phẩm còn hàng lên đầu, hết hàng xuống cuối. Cần thêm custom meta query.

Lưu ý quan trọng khi thêm code vào functions.php

1. Luôn dùng child theme: Nếu bạn thêm code trực tiếp vào functions.php của parent theme, tất cả thay đổi sẽ bị mất khi theme update. Hãy tạo child theme hoặc dùng plugin Code Snippets để quản lý code custom.

2. Clear cache sau khi sửa: Nếu website dùng page cache (LiteSpeed Cache, WP Rocket, v.v.), hãy clear cache sau khi thêm hoặc sửa code. Nếu không, bạn sẽ không thấy thay đổi ngay lập tức và có thể tưởng rằng code không hoạt động.

3. Kiểm tra product variation: Nếu bạn bán sản phẩm có biến thể (variable products), sắp xếp theo ngày tháng có thể gây confusing khi một sản phẩm cha có nhiều biến thể được đăng ở các thời điểm khác nhau. Trong trường hợp này, hãy cân nhắc sắp xếp theo modified thay vì date để lấy ngày cập nhật gần nhất.

4. Cân nhắc hiệu năng: Sort theo date, title hay popularity đều nhanh vì đây là các trường có index sẵn trong database. Tuy nhiên, nếu bạn sort theo custom meta field không có index, query sẽ chậm hơn đáng kể với danh sách sản phẩm lớn. Hãy thêm database index cho custom meta nếu cần.

Kết luận

Vấn đề sắp xếp sản phẩm theo ngày tháng khi dùng nhiều danh mục con trong WooCommerce là một case khá đặc thù nhưng lại gặp phải nhiều trong thực tế. Chỉ với một đoạn code ngắn trong functions.php, bạn có thể thay đổi hoàn toàn cách WooCommerce hiển thị sản phẩm, giúp trang danh mục trông gọn gàng và logic hơn.

Nếu bạn chỉ cần quick fix, dùng Giải pháp 1 là đủ. Nếu cần kiểm soát chi tiết hơn, hãy dùng Giải pháp 2 hoặc 3. Và đừng quên luôn dùng child theme để bảo vệ code custom của mình khỏi việc bị mất khi update theme.

Xem thêm: Sắp xếp nhanh sản phẩm hết hàng về cuối với file functions.php

Thực ra mình chỉ là người dùng tự mày mò, toàn bộ kiến thức trong bài đến từ quá trình vọc vạch cá nhân. Nội dung này không thay thế được một website được dựng đúng nghĩa. Nếu bạn cần dựng tử tế, có thể tham khảo đội ngũ thiết kế web chuyên – mình hay giới thiệu bạn bè qua TaigaWeb.

Nhiều Lượt xem

Giới thiệuLiên hệChính sách Biên tập