Walker_Nav_Menu: put custom code between a particular <li>
سؤال
I'm attempting to add my logo to the middle of my navbar, and while looking at the nav walker class I couldn't figure what the best way to do this would be.
So my question is essentially how do I do that. the Walker_Nav_Menu() method start_el() seems to build only one li so where is it iterating over all of them and writing them to file.
المحلول
You need to make your own walker menu (i am guessing you already know that), and the best way i think is overriding the function that ends
each menu item which is end_el
:
class logo_in_middle_Menu_Walker extends Walker_Nav_Menu {
public $menu_location = 'primary';
function __construct($menu_location_var) {
// parent class doesnt have a constructor so no parent::__construct();
$this->menu_location = $menu_location_var;
}
public function end_el(&$output, $item, $depth = 0, $args = array()) {
$locations = get_nav_menu_locations(); //get all menu locations
$menu = wp_get_nav_menu_object($locations[$this->menu_location]); //one menu for one location so lets get the menu of this location
$menu_items = wp_get_nav_menu_items($menu->term_id);
$top_lvl_menu_items_count = 0; //we need this to work with a menu with children too so we dont use simply $menu->count here
foreach ($menu_items as $menu_item) {
if ($menu_item->menu_item_parent == "0") {
$top_lvl_menu_items_count++;
}
}
$total_menu_items = $top_lvl_menu_items_count;
$item_position = $item->menu_order;
$position_to_have_the_logo = ceil($total_menu_items / 2);
if ($item_position == $position_to_have_the_logo && $item->menu_item_parent == "0") { //make sure we output for top level only
$output .= "</li>\n<img src='PATH_TO_YOUR_LOGO' alt='' />"; //here we add the logo
} else {
$output .= "</li>\n";
}
}
}
i am assuming that if its a menu with an uneven number of item say 5 the logo will be after the third element, also that this is only for top elements only.
you have to use it like this in the menu location:
<?php
wp_nav_menu(array(
'theme_location' => 'footer',
"walker" => new logo_in_middle_Menu_Walker('footer'),
));
?>
you have to supply the name of the theme location.
Here with 4 items:
Here with 5:
نصائح أخرى
Modified David Lees nav walker class as for some reason it wouldn't quite work for me with submenu links. Unverified, but believe this was due to the menu items not having tidy/sequential menu_order values.
<?php
class logo_in_middle_Menu_Walker extends Walker_Nav_Menu {
public $menu_location = 'primary';
function __construct($menu_location_var) {
$this->menu_location = $menu_location_var;
}
public function end_el(&$output, $item, $depth = 0, $args = array())
{
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object($locations[$this->menu_location]);
$menu_items = wp_get_nav_menu_items($menu->term_id);
$top_level_items = [];
foreach ( $menu_items as $menu_item ) {
if ( $menu_item->menu_item_parent == 0 ) {
$top_level_items[] = $menu_item;
}
}
$logo_position = ceil(count($top_level_items) / 2);
if ( $item->menu_item_parent == 0 ) {
$current_position = 0;
foreach ( $top_level_items as $index => $top_level_item ) {
if ( $top_level_item->ID == $item->ID ) {
$current_position = $index + 1;
}
}
if ( $current_position == $logo_position ) {
$output .= '</li>' . "\n";
$output .= '<li class="logo">' . "\n";
$output .= '<img src="PATH_TO_YOUR_LOGO" alt="LOGO ALT" />' . "\n";
}
}
$output .= "</li>\n";
}
}
The best way to achieve the desired functionality, is to add a new menu item for the logo, by going to the Appearance > Menus, and set the class of the menu item to logo.
To enable custom CSS class in the menu, click the Screen Options then check the CSS Classes checkbox.
Let's assume you have a predetermined number of li
items of 5.
<ul>
<li class="logo">LOGO</li>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
Then set the main ul
element css display attribute to flex
:
ul {
display: flex
}
And the li
order number as follows:
ul li { order: 4; }
ul li:nth-of-type(2) { order: 1; } /* For Item 1 */
ul li:nth-of-type(3) { order: 2; } /* For Item 2 */
Then for the logo class:
ul li.logo {
order: 3;
}
You can learn for about the order property of the Flexible Box Layout