Vấn đề danh mục bị xáo trộn trong giao diện chỉnh sửa
Bạn đã từng khó chịu khi hệ thống WordPress của bạn có quá nhiều danh mục được phân cấp, nhưng khi vào giao diện chỉnh sửa bài viết thì tất cả danh mục đã chọn bị đẩy lên trên cùng (top), làm hỏng hoàn toàn cấu trúc cha/con? Đây là một vấn đề rất phổ biến mà nhiều người dùng WordPress gặp phải, đặc biệt là các website WooCommerce có nhiều danh mục sản phẩm phân cấp sâu.

Hành vi này do thiết kế mặc định của WordPress. Khi bạn mở bảng chọn danh mục (category checklist) trong trình chỉnh sửa bài viết, WordPress sẽ tự động đặt các danh mục đã được check lên vị trí đầu tiên của danh sách. Mục đích của thiết kế này là giúp người dùng nhanh chóng thấy những danh mục đang được chọn. Tuy nhiên, khi danh mục có cấu trúc phân cấp phức tạp (ví dụ: Điện thoại > Samsung > Galaxy S系列), việc đưa các item đã chọn lên top sẽ phá vỡ hoàn toàn cấu trúc phân cấp, khiến bạn khó xác định được mối quan hệ cha/con.
Điều này đặc biệt gây khó chịu khi website có hàng chục hoặc hàng trăm danh mục được tổ chức theo cây phân cấp. Bạn không thể nào biết được danh mục vừa check thuộc nhóm nào nếu chúng bị tách rời khỏi cấu trúc gốc.
Code giữ nguyên cấu trúc danh mục
Giải pháp rất đơn giản. Bạn chỉ cần thêm một đoạn code ngắn vào file functions.php của theme đang sử dụng:
/**
* Giu nguyen cau truc phan cap cua danh muc
* khi chinh sua bai viet trong admin
* Set 'checked_ontop' = false de khong dua
* danh muc da chon len vi tri dau tien
*/
add_filter( 'wp_terms_checklist_args', function( $args, $post_id ) {
$args['checked_ontop'] = false;
return $args;
}, 10, 2 );
Giải thích cách hoạt động:
WordPress sử dụng hàm wp_terms_checklist_args để cấu hình danh sách checkbox của taxonomy (category, tag, custom taxonomy) trong trình chỉnh sửa bài viết. Tham số checked_ontop mặc định có giá trị true, chính nó là nguyên nhân khiến các danh mục đã chọn bị đẩy lên đầu danh sách. Bằng cách đặt giá trị này thành false qua filter, chúng ta yêu cầu WordPress giữ nguyên vị trí gốc của từng danh mục trong cây phân cấp, chỉ đánh dấu checked tại vị trí của chúng.
Filter này nhận hai tham số: $args chứa các cấu hình hiện tại của checklist, và $post_id là ID của bài viết đang chỉnh sửa. Chúng ta chỉ cần sửa giá trị checked_ontop rồi trả lại mảng $args.

Áp dụng cho custom taxonomy
Đoạn code trên áp dụng cho tất cả taxonomy trong WordPress, bao gồm cả custom taxonomy mà bạn hoặc plugin tạo ra. Điều này có nghĩa là nó sẽ hoạt động với:
– Categories (danh mục bài viết): Phân loại mặc định của WordPress posts.
– Tags (thẻ): Tuy nhiên tags thường không có phân cấp nên ít ảnh hưởng.
– Product Categories (danh mục sản phẩm WooCommerce): Đây là nơi filter này phát huy tác dụng mạnh nhất vì WooCommerce thường có danh mục sản phẩm phân cấp rất sâu.
– Custom Taxonomy: Bất kỳ taxonomy tùy chỉnh nào có phân cấp hierarchical.
Nếu bạn chỉ muốn áp dụng cho một taxonomy cụ thể, có thể thêm điều kiện kiểm tra:
// Chi ap dung cho product_cat (danh muc san pham WooCommerce)
add_filter( 'wp_terms_checklist_args', function( $args, $post_id ) {
if ( isset( $args['taxonomy'] ) && $args['taxonomy'] === 'product_cat' ) {
$args['checked_ontop'] = false;
}
return $args;
}, 10, 2 );
Hướng dẫn thêm code an toàn vào theme
Cách 1: Dùng child theme. Đây là cách được khuyến nghị nhất. Tạo child theme từ theme hiện tại, sau đó thêm code vào file functions.php của child theme. Khi theme cha cập nhật, code của bạn không bị mất. Nếu bạn đang dùng Bricks Builder, theme Bricks có sẵn hỗ trợ child theme.
Cách 2: Dùng plugin Code Snippets. Cài plugin Code Snippets miễn phí từ WordPress repository. Plugin này tạo giao diện quản lý code PHP riêng, bạn có thể bật/tắt từng đoạn code một cách dễ dàng mà không cần đụng đến file theme.
Cách 3: Dùng WP Code (trước đây là Insert Headers and Footers). Plugin miễn phí khác cho phép thêm code PHP, CSS, JavaScript qua giao diện admin. Giao diện thân thiện, phù hợp người mới.
Kết hợp với editor Gutenberg và Classic Editor
Đoạn code hoạt động với cả Gutenberg (block editor) và Classic Editor. Trong Gutenberg, khi bạn nhấp vào bảng chọn danh mục trong panel Taxonomy bên phải, các danh mục sẽ giữ nguyên cấu trúc phân cấp. Trong Classic Editor, bảng chọn danh mục trong metabox cũng hiển thị đúng cấu trúc.
Lưu ý rằng với Gutenberg, một số theme hoặc plugin có thể dùng sidebar panel tùy chỉnh thay vì metabox taxonomy mặc định. Nếu vậy, filter này có thể không tác động lên panel tùy chỉnh đó, vì panel đó sử dụng JavaScript riêng để render checklist. Tuy nhiên trong hầu hết trường hợp, WordPress vẫn dùng wp_terms_checklist_args làm nguồn dữ liệu.
Tối ưu trải nghiệm quản lý danh mục
Ngoài việc giữ cấu trúc phân cấp, bạn có thể cải thiện thêm trải nghiệm quản lý danh mục với các mẹo sau:
1. Sử dụng plugin Category Order and Taxonomy Terms Order: Plugin miễn phí cho phép bạn kéo thả để sắp xếp thứ tự danh mục theo ý muốn thay vì chỉ theo tên hay ID. Kết hợp với code trên, bạn sẽ có một danh mục được sắp xếp hoàn hảo.
2. Thêm CSS cho metabox taxonomy: Nếu metabox danh mục bị quá dài, bạn có thể thêm CSS để tăng chiều cao hoặc tạo thanh cuộn mượt hơn trong admin:
add_action( 'admin_head', function() {
echo '<style>
.categorydiv div.tabs-panel {
max-height: 500px;
overflow-y: auto;
}
.categorydiv .categorychecklist li {
padding: 4px 0;
}
/* Hien thi muc indent ro rang hon */
.categorydiv .children {
margin-left: 20px;
}
</style>';
} );
3. Giới hạn độ sâu phân cấp: Mặc dù WordPress cho phép danh mục phân cấp không giới hạn, nhưng nên giới hạn ở mức 2-3 cấp. Phân cấp quá sâu khiến cả người quản lý lẫn người dùng đều khó tìm kiếm.
Một số vấn đề thường gặp
Code không hoạt động với custom post type: Filter wp_terms_checklist_args hoạt động cho mọi post type sử dụng taxonomy metabox mặc định. Nếu custom post type của bạn dùng UI riêng (ví dụ ACF, MetaBox.io), filter này không tác động. Trong trường hợp đó, bạn cần tìm filter hoặc action riêng của plugin đó.
Xung đột với plugin khác: Một số plugin SEO hoặc quản lý taxonomy có thể ghi đè tham số checked_ontop. Nếu code không hoạt động, hãy thử tăng priority từ 10 lên 999 hoặc tắt tạm plugin khác để kiểm tra xung đột.
Không thấy thay đổi sau khi thêm code: Xóa cache của browser và cache plugin (nếu có). Nếu dùng Object Cache như Redis hoặc Memcached, hãy flush cache để đảm bảo filter được nạp lại.
Tổng kết
Với chỉ một dòng code quan trọng $args['checked_ontop'] = false; trong filter wp_terms_checklist_args, bạn có thể giữ nguyên cấu trúc phân cấp của danh mục trong giao diện chỉnh sửa bài viết. Giải pháp này áp dụng cho mọi taxonomy có phân cấp, hoạt động với cả Gutenberg và Classic Editor. Hãy nhớ dùng child theme hoặc plugin Code Snippets để bảo vệ code khi cập nhật theme.
Xem thêm: Hướng dẫn tối ưu bài viết chuẩn SEO hoặc Hướng dẫn tải file SVG lên WordPress an toàn.
Đây là bài mình ghi chép sau khi vọc – không phải hướng dẫn từ chuyên gia, mà là kinh nghiệm xương máu của một người dùng tự mày mò. Nếu bạn muốn một website đàng hoàng ngay từ đầu, team làm WordPress chuyên nghiệp sẽ đỡ mất thời gian hơn – TaigaWeb là một đơn vị mình tin.

