Tuỳ biến cấu trúc menu WordPress với Walker_Nav_Menu [NEW]



Khi chúng ta thêm menu vào chủ đề trong WordPress theo cách thủ công bằng cách sử dụng hàm register_nav_menu và hiển thị nó bằng hàm wp_nav_menu, nó sẽ hiển thị với cấu trúc mặc định trong WordPress như menu con sẽ nằm trong thẻ. <ul> với lớp sub-menuhoặc mỗi thẻ <li> trong menu sẽ có một số lớp nhất định.

Nhưng giả sử dự án bạn cần làm việc có cấu trúc menu khác (điển hình là cấu trúc menu của Bootstrap hoặc Foundation) thì tất nhiên bạn sẽ cần phải sửa đổi cấu trúc menu của WordPress.

Trong bài viết này, tôi sẽ giải thích cho bạn về lớp Walker_Nav_Menu được sử dụng trong WordPress để thiết lập cấu trúc hiển thị của menu. Nếu chúng ta tạo một lớp khác kế thừa lớp này, chúng ta có thể đặt lại cấu trúc của các menu được chỉ định theo cách thủ công.

Hiểu trước khi thực hiện:

  • Cách tạo menu trong WordPress
  • Cấu trúc chủ đề trong WordPress

Sử dụng Walker trong Menu

Walker là một lớp trong WordPress để cấu hình cấu trúc của một số chức năng như cấu trúc menu, cấu trúc Category widget, cấu trúc Pages widget. Trong bài này, chúng tôi chỉ sử dụng Walker trong việc chỉnh sửa cấu trúc menu.

Để có thể chỉ định một menu nhất định để hiển thị bên ngoài chủ đề với cấu trúc có thể định cấu hình Walker_Nav_Menu của bạn thì bạn phải kích hoạt nó bằng cách thêm thông số walker vào chức năng wp_nav_menu.


$thachpham_walker = new ThachPham_Nav_Walker;
wp_nav_menu( array(
‘theme_location’ => ‘primary’,
‘menu_class’ => ‘nav-menu’,
‘menu_id’ => ‘primary-menu’,
‘walker’ => $thachpham_walker
) );

Hai đoạn tôi tô đậm có nghĩa là lần đầu tiên tôi tạo một đối tượng mới có tên $thachpham_walker từ lớp họcThachPham_Nav_Walker thì tôi sẽ sử dụng đối tượng này làm tham số walker của chức năng wp_nav_menu.

Vậy ThachPham_Nav_Walker ở đâu? Đã tạo ở đâu khác: D, bây giờ chúng ta sẽ tạo nó và kế thừa lại lớp Walker_Nav_Menuvà chứa một số phương thức trừu tượng như sau:


class ThachPham_Nav_Walker extends Walker_Nav_Menu {

/**
* Phương thức start_lvl()
* Được sử dụng để hiển thị các thẻ bắt đầu cấu trúc của một cấp độ mới trong menu. (ví dụ: <ul class="sub-menu">)
* @param string $output | Sử dụng để thêm nội dung vào những gì hiển thị ra bên ngoài
* @param interger $depth | Cấp độ hiện tại của menu. Cấp độ 0 là lớn nhất.
* @param array $args | Các tham số trong hàm wp_nav_menu()
**/
public function start_lvl( &$output, $depth = 0, $args = array() )
{

}

/**
* Phương thức end_lvl()
* Được sử dụng để hiển thị đoạn kết thúc của một cấp độ mới trong menu. (ví dụ: </ul> )
* @param string $output | Sử dụng để thêm nội dung vào những gì hiển thị ra bên ngoài
* @param interger $depth | Cấp độ hiện tại của menu. Cấp độ 0 là lớn nhất.
* @param array $args | Các tham số trong hàm wp_nav_menu()
**/
public function end_lvl( &$output, $depth = 0, $args = array() )
{

}

/**
* Phương thức start_el()
* Được sử dụng để hiển thị đoạn bắt đầu của một phần tử trong menu. (ví dụ: <li id="menu-item-5"> )
* @param string $output | Sử dụng để thêm nội dung vào những gì hiển thị ra bên ngoài
* @param string $item | Dữ liệu của các phần tử trong menu
* @param interger $depth | Cấp độ hiện tại của menu. Cấp độ 0 là lớn nhất.
* @param array $args | Các tham số trong hàm wp_nav_menu()
* @param interger $id | ID của phần tử hiện tại
**/
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
{

}

/**
* Phương thức end_el()
* Được sử dụng để hiển thị đoạn kết thúc của một phần tử trong menu. (ví dụ: </li> )
* @param string $output | Sử dụng để thêm nội dung vào những gì hiển thị ra bên ngoài
* @param string $item | Dữ liệu của các phần tử trong menu
* @param interger $depth | Cấp độ hiện tại của menu. Cấp độ 0 là lớn nhất.
* @param array $args | Các tham số trong hàm wp_nav_menu()
* @param interger $id | ID của phần tử hiện tại
**/
public function end_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
{

}
} // end ThachPham_Nav_Walker

Ý nghĩa của các phương pháp, vui lòng xem các bình luận trong mã. Và để xem toàn bộ mã của lớp Walker_Nav_Menuvui lòng xem mã dòng 10 đến dòng 191 trong /wp-includes/nav-menu-template.php của mã nguồn WordPress. Chúng tôi sẽ làm việc bằng cách tùy chỉnh mã trong phần này mà không cần chạm vào mã nguồn, bằng cách kế thừa Walker_Nav_Menu cho lớp học ThachPham_Nav_Walker của tôi.

Lưu ý rằng bạn cần tùy chỉnh phương thức nào thì chỉ cần khai báo phương thức đó, không cần khai báo tất cả. Nếu đã khai báo rồi thì phải viết code như đã được định nghĩa sẵn trong /wp-includes/nav-menu-template.php, nếu khai báo sai hoặc thiếu sẽ gây ra lỗi.

Làm việc với start_lvl ()

Như tôi đã nói trong mã, phương pháp start_lvl() được sử dụng để đặt lại các thẻ mở của cấp menu mới, từ cấp menu ban đầu. Điều này có nghĩa là chúng tôi sẽ sử dụng phương pháp này để thay đổi cấu trúc của thẻ <ul class="sub-menu"> WordPress mặc định trong menu con.

Trong tệp /wp-includes/nav-menu-template.php, từ đoạn 47 đến 50, nó đặt phương thức này như sau:


public function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("t", $depth);
$output .= "n$indent<ul class="sub-menu">n";
}

Đoạn trên có nghĩa là nó sẽ lặp lại chuỗi t tương ứng với giá trị của $depth (nếu menu đó có cấp độ 2 thì nó lặp lại t 2 lần) và sau đó đặt nó vào biến $indent. Trong PHP, ký tự t có nghĩa là một tab (khoảng trắng trước ký tự). Sau đó, nó sẽ sử dụng biến $indent Cái này cho $output để hiển thị với n$indent, n tức là ký tự đại diện cho một hàng văn bản. Vì vậy, ý nghĩa của đoạn văn trên là nó in <ul class="sub-menu"> thụt lề so với phần tử trước đó, như thế này:


<li>
<ul class="sub-menu">
<li>Level 1</li>
</ul>

Và khoảng trống phía trước thẻ <ul>t ở đó.

Thực hành: Thêm nội dung trước

Trong bài học này, chúng ta sẽ thực hành bằng cách thêm thẻ <span> ở phía trước menu con, vì vậy sẽ viết mã cho phương thức start_lvl() Trong lớp ThachPham_Nav_Walker như sau:


public function start_lvl( & $output, $depth, $args )
{
$indent = str_repeat("t", $depth);
$output .= "<span class="sub-intro">Menu con</span>";
$output .= "n$indent<ul class="sub-menu">n";
}

Sử dụng phương thức end_lvl ()

Phương pháp end_lvl() Ứng dụng này khá đơn giản, đó là nó sẽ hiển thị phần cuối của một mức menu mới, tức là thẻ </ul>.

Từ đoạn 63 đến đoạn 66 trong /wp-includes/nav-menu-template.php, nó được khai báo như sau:


public function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("t", $depth);
$output .= "$indent</ul>n";
}

Ý nghĩa giống như start_lvl() chỉ, sự khác biệt duy nhất là nó có nhiều hơn </ul>.

Sử dụng phương thức start_el ()

Phương pháp này có lẽ là phương pháp chúng tôi sẽ làm việc nhiều nhất trong Walker_Nav_Menu vì nó sẽ đặt lại cấu trúc hiển thị của

  • các yếu tố trong menu. Trước khi sử dụng nó, bạn cần đọc qua mã của phương thức này từ dòng 81 đến 173 trong /wp-includes/nav-menu-template.php. Và ở đây tôi sẽ giải thích chi tiết ý nghĩa của các mã trong phần này của lớp Walker_Nav_Menu gốc trong tệp này.

    Dòng số 82 chúng ta có biến $indent là đặt khoảng trắng với ký tự t để nó hiển thị thẻ <li> để thụt lề (xem dòng 115).

    $indent = ( $depth ) ? str_repeat( "t", $depth ) : ”;

    Dòng 84 và 85 có nghĩa là nó sẽ lấy ID của đối tượng trong menu thông qua đối tượng dữ liệu $item->ID và nối vào đối tượng $item->classes để hiển thị các lớp HTML tượng trưng cho từng đối tượng trong menu (ví dụ: lớp menu-item-83), các lớp sau khi ghép sẽ được đưa vào biến $classes.


    $classes = empty( $item->classes ) ? array() : (array) $item->classes;
    $classes[] = ‘menu-item-‘ . $item->ID;

    Tiếp theo trên dòng 98 và 99, sau biến $classes ở trên, ở hai dòng này nó sẽ tiến hành trích xuất các giá trị trong mảng $classes để hiển thị phần tử menu được phân tách bằng dấu cách. Trong đoạn này, bạn sẽ thấy dòng apply_filters với cái móc có tên nav_menu_css_classsau này bạn cần làm gì liên quan đến chỉnh sửa class trong menu thì chỉ cần dùng add_filter để lọc qua hook này.


    $class_names = join( ‘ ‘, apply_filters( ‘nav_menu_css_class’, array_filter( $classes ), $item, $args, $depth ) );
    $class_names = $class_names ? ‘ class="’ . esc_attr( $class_names ) . ‘"’ : ”;

    Dòng 112 và 113 tương tự như 98 và 99 nhưng nó chịu trách nhiệm thiết lập ID của từng phần tử trong menu.


    $id = apply_filters( ‘nav_menu_item_id’, ‘menu-item-‘. $item->ID, $item, $args, $depth );
    $id = $id ? ‘ id="’ . esc_attr( $id ) . ‘"’ : ”;

    Dòng 115 là cài đặt những gì nó sẽ hiển thị ra bên ngoài. Ở đây bạn có thể hiểu đơn giản là nó in thẻ <li> với ID và Lớp trong hai biến $class_names $id ở trên.


    $output .= $indent . ‘<li’ . $id . $class_names .’>’;

    Dòng 117 đến 121 có nghĩa là nó sẽ đặt một số thuộc tính của mỗi phần tử danh sách trong menu vào mảng $ atts để sau này nó sẽ sử dụng lại foreach với mục đích tách các giá trị để hiển thị với thẻ. a.


    $atts = array();
    $atts[‘title’] = ! empty( $item->attr_title ) ? $item->attr_title : ”;
    $atts[‘target’] = ! empty( $item->target ) ? $item->target : ”;
    $atts[‘rel’] = ! empty( $item->xfn ) ? $item->xfn : ”;
    $atts[‘href’] = ! empty( $item->url ) ? $item->url : ”;

    Tôi đưa ra một ví dụ cho những bạn chưa hiểu, ví dụ như đoạn này:

    $atts[‘title’]  = ! empty( $item->attr_title ) ? $item->attr_title : ”;

    Đó là, nếu $item->attr_title có một giá trị (phủ định của rỗng) thì nó sẽ gọi $item->attr_title đầu ra (đối tượng này sẽ trả về nội dung của thuộc tính Title của menu). Nếu không, không làm gì cả (được biểu thị bằng hai ký tự ' ').

    Đoạn 151 đến 156 là nó sẽ hiển thị cấu trúc của phần tử bên trong <li> ra, các phần tử này được chứa trong biến $item_output.


    $item_output = $args->before;
    $item_output .= ‘<a’. $attributes .’>’;
    /** This filter is documented in wp-includes/post-template.php */
    $item_output .= $args->link_before . apply_filters( ‘the_title’, $item->title, $item->ID ) . $args->link_after;
    $item_output .= ‘</a>’;
    $item_output .= $args->after;

    Thực hành: Hiển thị Mô tả của đối tượng menu.

    Nếu chúng ta muốn hiển thị Mô tả của đối tượng trong menu ra bên ngoài thì trước tiên chúng ta khai báo thêm 1 dòng với biến $ item_output, mình kiểm tra xem có mô tả thì sẽ hiển thị.


    $item_output = $args->before;
    $item_output .= ‘<a’. $attributes .’>’;
    /** This filter is documented in wp-includes/post-template.php */
    $item_output .= $args->link_before . apply_filters( ‘the_title’, $item->title, $item->ID ) . $args->link_after;
    $item_output .= ‘</a>’;
    $item_output .= !empty( $atts[‘description’] ) ? ‘<span class="description">’ . esc_attr( $atts[‘description’] ) . ‘</span>’ : ”;
    $item_output .= $args->after;

    Kết quả:

    Tuỳ biến cấu trúc menu WordPress với Walker_Nav_Menu [NEW]


    public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
    {
    $indent = ( $depth ) ? str_repeat( "t", $depth ) : ”;

    $classes = empty( $item->classes ) ? array() : (array) $item->classes;
    $classes[] = ‘menu-item-‘ . $item->ID;

    $class_names = join( ‘ ‘, apply_filters( ‘nav_menu_css_class’, array_filter( $classes ), $item, $args, $depth ) );
    $class_names = $class_names ? ‘ class="’ . esc_attr( $class_names ) . ‘"’ : ”;

    $id = apply_filters( ‘nav_menu_item_id’, ‘menu-item-‘. $item->ID, $item, $args, $depth );
    $id = $id ? ‘ id="’ . esc_attr( $id ) . ‘"’ : ”;

    $output .= $indent . ‘<li’ . $id . $class_names .’>’;

    $atts = array();
    $atts[‘title’] = ! empty( $item->attr_title ) ? $item->attr_title : ”;
    $atts[‘target’] = ! empty( $item->target ) ? $item->target : ”;
    $atts[‘rel’] = ! empty( $item->xfn ) ? $item->xfn : ”;
    $atts[‘href’] = ! empty( $item->url ) ? $item->url : ”;

    $atts = apply_filters( ‘nav_menu_link_attributes’, $atts, $item, $args, $depth );

    $attributes = ”;
    foreach ( $atts as $attr => $value ) {
    if ( ! empty( $value ) ) {
    $value = ( ‘href’ === $attr ) ? esc_url( $value ) : esc_attr( $value );
    $attributes .= ‘ ‘ . $attr . ‘="’ . $value . ‘"’;
    }
    }

    $item_output = $args->before;
    $item_output .= ‘<a’. $attributes .’>’;
    /** This filter is documented in wp-includes/post-template.php */
    $item_output .= $args->link_before . apply_filters( ‘the_title’, $item->title, $item->ID ) . $args->link_after;
    $item_output .= ‘</a>’;
    $item_output .= !empty( $atts[‘description’] ) ? ‘<span class="description">’ . esc_attr( $atts[‘description’] ) . ‘</span>’ : ”;
    $item_output .= $args->after;

    $output .= apply_filters( ‘walker_nav_menu_start_el’, $item_output, $item, $depth, $args );
    }

    Sử dụng phương thức end_el ()

    Phương pháp này giống như end_lvl()để nó hiển thị phần cuối của phần tử <li> trong menu.

    Từ dòng 187 đến 189 trong /wp-includes/nav-menu-template.php, nó đã được thiết lập như thế này:


    public function end_el( &$output, $item, $depth = 0, $args = array() ) {
    $output .= "</li>n";
    }

    Một số thư viện Walker Nav Menu có sẵn

    Dưới đây là danh sách các thư viện máy tập đi bộ với các tính năng khác nhau có sẵn mà bạn có thể sử dụng lại trên internet:

    • wp-bootstrap-navwalker – Thư viện walker để hiển thị các menu có cấu trúc Bootstrap.
    • wp-foundation-walker – Thư viện Walker để hiển thị menu trong cấu trúc của Foundation.
    • Clean-Menu-Walker – Thư viện Walker để hiển thị các menu nhỏ gọn hơn, loại bỏ các lớp không cần thiết.

    Phần kết

    Trong bài viết này có thể mình viết hơi dài và giải thích quá kỹ so với quy định, tuy nhiên việc giải thích cặn kẽ như vậy cũng sẽ giúp các bạn phần nào hiểu rõ hơn, tránh những thắc mắc hay những vấn đề dễ hiểu nhầm. Do đó, nếu bạn đọc xong mà vẫn chưa hiểu thì hãy xem video ở đầu bài viết.

    Đánh giá nội dung này