Để tùy biến can thiệp vào từng category bạn muốn hiển thị hoặc không muốn hiển thị trong danh sách categories bạn liệt kê ở sidebar widget thì chúng ta sử dụng tham số walker cũng giống với cách tùy biến với nav menu nhưng kế thừa class Walker_Category.
Walker là class đặc biệt cho việc hiển thị cấu trúc cây của menu, categories, pages, comments trong wordpress. Điển hình hàm wp_list_categories() có tham số walker giúp bạn tùy chỉnh bất kỳ dữ liệu danh mục nào bạn muốn hiển thị có kết hợp với template tags.
Đầu tiên, chúng ta tạo class kế thừa Walker_Category. Chép nội dung class sau vào functions.php hoặc viết vào plugin mới. Nhưng cho đơn giản bạn có thể thêm vào trong theme functions.php để có kết quả ngay.
class Post_Category_Walker extends Walker_Category {
private $term_ids = array();
function __construct( $post_id, $taxonomy ) {
// fetch the list of term ids for the given post
$this->term_ids = wp_get_post_terms( $post_id, $taxonomy, 'fields=ids' );
}
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
$display = false;
$id = $element->term_id;
if ( in_array( $id, $this->term_ids ) ) {
// the current term is in the list
$display = true;
}
elseif ( isset( $children_elements[ $id ] ) ) {
// the current term has children
foreach ( $children_elements[ $id ] as $child ) {
if ( in_array( $child->term_id, $this->term_ids ) ) {
// one of the term's children is in the list
$display = true;
// can stop searching now
break;
}
}
}
if ( $display ) parent::display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output );
}
}
Lưu ý: Tương tự như cách làm việc của Menu Walker. Walker_Category và Walker_Nav_Menu có kế thừa base class chung là Walker. Vì vậy có thể override các phương thức thuộc về Walker class như: display_element, start_lvl, end_lvl, start_el, end_el.
ở đây chúng ta thấy có hàm display_element(), hàm này được gọi cho mỗi category và quyết định cho từng category được hiển thị hoặc không bằng cách gọi mặc định phương thức mẹ parent::display_element của nó. Hàm override này quét tất cả những categories, categories nào thuộc về post có chỉ định $id xác định qua constructor sẽ cho hiển thị bao gồm parent categories và cả subcategories.
Tạo đối tượng walker cho hàm hiển thị danh mục categories trong wordpress wp_list_categorie, ví dụ đưa vào hàm sau:
function walk_post_categories($post_id, $args = array()) {
$args = wp_parse_args($args, array(
'taxonomy' => 'category',
));
$args['walker'] = new Post_Category_Walker($post_id, $args['taxonomy']);
$output = wp_list_categories($args);
if ($output) {
return $output;
}
}
Để hiển thị các danh mục của bài viết theo cấu trúc tầng chúng ta truyền post vào hàm :
<?php walk_post_categories(123);?>
Đưa thêm tham số vào hàm wp_list_categories nếu muốn.
Hàm start_lvl có vai trò tạo thẻ html bao các categories con, thường là ul, ol tùy theo bạn thiết lập. Mặc định là tag ul. Chúng ta có thể hiển thị danh mục con bên dưới danh mục mẹ hoặc chỉ hiển thị danh mục mẹ với thuộc tính hierarchical.
Do vậy để sử dụng phương thức start_lvl và end_lvl hãy chắc chắn có thiết lập thuộc tính “hierarchical=true”.
wp_list_categories(array('hierarchical'=>true));
Hàm wp_list_categories cũng cho phép loại bỏ wrap bao ngoài toàn bộ danh mục bằng cách khai báo thuộc tính ‘title_li‘ với giá trị chuỗi rỗng.
wp_list_categories(array('title_li'=>''));
Kết quả chỉ còn các thẻ bao nội dung mỗi category, nếu style=”list” thì hàm wp_list_categories trả về sẽ như thế này.
Tuy nhiên nếu có thiết lập tham số ‘title_li’ thì kết quả có thêm thẻ bao li hoặc ul bên ngoài dữ liệu categories, khi Inspect Element trên chrome bạn sẽ thấy như sau:
Không có cách nào loại bỏ với bắt đầu bằng thẻ li của wp_list_categories, nhưng bạn có thể dùng css tạo style cho thẻ li này.
Tham khảo một số phương thức walker có thể dùng đến cho website của bạn, sẽ rất hữu ích khi bạn muốn chỉnh sửa HTML trong cấu trúc hiển thị dữ liệu mặc định category/Menu.
Đối với category widget, wordpress cung cấp cho chúng ta hook widget_categories_args để thiết lập thêm tham số cho hàm wp_list_categories của category widget. Sau khi kéo widget category trên sidebar sẽ hiển thị ra website, chúng ta chèn đoạn code sau đây vào theme functions.php. Lưu ý là wordpress không có mọi tùy chỉnh nâng cao với widget này mà bạn phải code ngoài nhé.
function my_wp_list_categories($cat_args) {
global $post;
$tax = get_object_taxonomies($post);
$cat_args['title_li'] = 'ABC';
$cat_args['exclude'] = 1;
$cat_args['use_desc_for_title'] = 0;
$cat_args['walker'] = new Post_Category_Walker($post->ID, $tax[1]);
return $cat_args;
}
add_filter('widget_categories_args', 'my_wp_list_categories', 10, 2);
Không hiểu sao categories widget mặc định trong wordpress không hỗ trợ đầy đủ walker, phương thức start_lvl và end_lvl không hoạt động. Mình thử với plugin Display Categories Widget thì hoạt động tốt. Phiên bản gốc hiện tại không có tùy chọn option Walker tuy nhiên mình đã can thiệp thêm cài đặt này cho phép bạn điền class Walker để sử dụng tính năng này. Sửa code plugin cũng rất đơn giản với nhưng bạn thành thạo PHP, nếu ai không biết thì liên hệ với mình nha.
Ngoài ra sử dụng filter “wp_list_categories” bạn có thể thêm, sửa, xóa toàn phần hiển thị HTML của hàm wp_list_categories.
add_filter('wp_list_categories','filter_wp_list_categories');
function filter_wp_list_categories($output){
....
return $output;
}
Chú ý: nếu gặp lỗi ‘escape slashes’ sẩy ra với thẻ html giống thế này,