When we proceed to manually add the menu to the theme in WordPress using the . function register_nav_menu and display using the function wp_nav_menu then it will show up with a default structure in WordPress like submenus will be inside a tag <ul>
with class sub-menu
or each card <li>
in the menu there will be certain classes.
But suppose the project you need to work on has a different menu structure (typically the menu structure of Bootstrap or Foundation) then of course you will need to modify the WordPress menu structure.
In this article, I will explain to you about the class Walker_Nav_Menu
which is used in WordPress to set the display structure of the menu. If we create another class that inherits this class, we can manually reset the structure of the specified menus.
Understand before doing:
Use Walker in Menu
To be able to specify a certain menu to display outside the theme with a configurable structure Walker_Nav_Menu
yours then you have to enable it by adding the parameter walker
into the function 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
) );
The two paragraphs I bolded mean I first created a new object named $thachpham_walker
from classThachPham_Nav_Walker
then I will use this object as the parameter walker
of the function wp_nav_menu
.
So where is the ThachPham_Nav_Walker? Created where else :D, now we will create it and inherit the class again Walker_Nav_Menu
and which contains some abstract methods as follows:
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 )
{}
/**
* The end_el() method
* Used to display the end of a menu element. (e.g. )
* @param string $output | Use to add content to what is visible to the outside
* @param string $item | Data of menu elements
* @param interger $depth | The current level of the menu. Level 0 is the largest.
* @param array $args | Parameters in wp_nav_menu() function
* @param interger $id | ID of the current element
**/
public function end_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
{}
} // end ThachPham_Nav_Walker
The meaning of the methods, please see the comments in the code. And to see the entire code of the class Walker_Nav_Menu
please see the code from line 10 to line 191 in file /wp-includes/nav-menu-template.php of the WordPress source code. We will work by customizing the code in this section without touching the source code, by inheritance Walker_Nav_Menu
for class ThachPham_Nav_Walker
mine.
Working with start_lvl()
As I said in the code, the method start_lvl()
used to reset the opening tags of a new menu level, from the original menu level. This means that we will use this method to change the structure of the card <ul class="sub-menu">
WordPress default in submenu.
In file /wp-includes/nav-menu-template.phpfrom paragraphs 47 to 50 is that it sets up this method as follows:
public function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("t", $depth);
$output .= "n$indent<ul class="sub-menu">n";
}
The above paragraph means it will repeat the string t
corresponds to the value of $depth
(if that menu has level 2 then it repeats t
2 times) and then put it in the variable $indent
. In PHP, the character t
means a tab (space before the character). Then it will use the variable $indent
this for $output
to show out with n$indent
, n
i.e. wildcard character for a row of text. So the meaning of the above paragraph is that it prints <ul class="sub-menu">
indented from the previous element, like this:
<li>
<ul class="sub-menu">
<li>Level 1</li>
</ul>
And the space in front of the tag <ul>
is t
there.
Practice: Add content before
In this lesson, we will practice by adding a tag <span>
in front of the submenu so will write the code for the method start_lvl()
in class ThachPham_Nav_Walker
as follows:
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";
}
Use the end_lvl() method
Method end_lvl()
The application is quite simple, that is it will display the end of a new menu level, i.e. the card </ul>
.
From paragraphs 63 to 66 in /wp-includes/nav-menu-template.php It is declared as follows:
public function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("t", $depth);
$output .= "$indent</ul>n";
}
The meaning is the same as the start_lvl()
only, the only difference is that it has more </ul>
.
Use the start_el() method
This method is probably the one we will work with the most in Walker_Nav_Menu
as it will reset the display structure of the
Line number 82 we have the variable $indent
is to set spaces with the character t
let it show the tag <li>
for indentation (see line 115).
$indent = ( $depth ) ? str_repeat( "t", $depth ) : ”;
Lines 84 and 85 mean that it will get the ID of the object in the menu through the data object $item->ID
and append to object $item->classes
to display symbolic HTML classes for each object in the menu (e.g. class menu-item-83
), the classes after being concatenated will be put into the variable $classes
.
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = ‘menu-item-‘ . $item->ID;
Next on lines 98 and 99, after the variable $classes
above, in these two lines it will proceed to extract the values in the array $classes
to display out the menu element separated by a space. In this paragraph, you will see the line apply_filters
with hook named nav_menu_css_class
later you need to do anything related to editing the class in the menu, just use add_filter to filter through this hook.
$class_names = join( ‘ ‘, apply_filters( ‘nav_menu_css_class’, array_filter( $classes ), $item, $args, $depth ) );
$class_names = $class_names ? ‘ class="’ . esc_attr( $class_names ) . ‘"’ : ”;
Lines 112 and 113 are similar to 98 and 99 but it is responsible for setting the ID of each element in the menu.
$id = apply_filters( ‘nav_menu_item_id’, ‘menu-item-‘. $item->ID, $item, $args, $depth );
$id = $id ? ‘ id="’ . esc_attr( $id ) . ‘"’ : ”;
Line 115 is the setting of what it should display to the outside. Here you can easily understand that it prints a card <li>
with ID and Class in two variables $class_names
and $id
above.
$output .= $indent . ‘<li’ . $id . $class_names .’>’;
Lines 117 to 121 means that it will put some properties of each list element in the menu into the $atts array so that it will use foreach again later for the purpose of separating the values to display with the tag. 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 : ”;
I give an example for those of you who don’t understand, for example this paragraph:
$atts[‘title’] = ! empty( $item->attr_title ) ? $item->attr_title : ”;
That is, if $item->attr_title
has a value (negation of empty) then it will call $item->attr_title
output (this object will return the contents of the menu’s Title property). Otherwise, do nothing (represented by two characters ' '
).
Paragraph 151 to 156 is that it will show the structure of the element inside <li>
out, these elements are contained in the variable $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;
Practice: Display the Description of the menu object.
If we want to display the Description of the object in the menu to the outside, then we will first declare one more line with the $item_output variable, I will check if there is a description, then it will display.
$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;
Result:
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 .= '';
/** 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 .= '';
$item_output .= !empty( $atts[‘description’] ) ? '' . esc_attr( $atts[‘description’] ) . '' : ”;
$item_output .= $args->after;$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
Use the end_el() method
This method is the same as end_lvl()
so that it shows the end of the element <li>
in the menu.
From line 187 to 189 in /wp-includes/nav-menu-template.php It’s already set up like this:
public function end_el( &$output, $item, $depth = 0, $args = array() ) {
$output .= "</li>n";
}
Several Walker Nav Menu libraries are available
Here is a list of walker libraries with various features available that you can reuse on the internet:
- wp-bootstrap-navwalker – Walker library to display the menu according to Bootstrap’s structure.
- wp-foundation-walker – Walker library to display the menu according to the Foundation’s structure.
- Clean-Menu-Walker – Walker library to display more compact menus, remove unnecessary classes.
Epilogue
In this article, I may have written a bit too long and explained it too carefully compared to the regulations, but such a thorough explanation will also help you somewhat better understand, avoiding questions or problems that are easily misunderstood. Therefore, if you have finished reading and still do not understand, please watch the video at the beginning of the article.
Source: Customize WordPress menu structure with Walker_Nav_Menu
– TechtipsnReview