W tym artykule zajmiemy się rejestracją i zaprogramowaniem menu we własnym szablonie WordPress. Aby poradnik był przydatny w wielu przypadkach, praktycznym przykładem będzie wielopoziomowe (lub jak kto woli rozwijane) menu.
Menu to tak naprawdę taki specjalny widget. Programowanie we własnym szablonie i zarządzanie z perspektywy redaktora strony bardzo przypomina korzystanie z widgetów. Jeżeli potrafisz stworzyć własny widget WordPress to ze stworzeniem własnego menu też nie będzie problemu.
Krok 1: Rejestracja menu
Każde menu trzeba najpierw zarejestrować. Kod prezentowałem w artykule o tworzeniu motywów WordPress:
function reg_mymenu() { register_nav_menu("header-menu",__("Menu główne")); } add_action("init", "reg_mymenu");
Taki kod możemy (a nawet powinno się) dodać do pliku functions.php.
Krok 2: Utworzenie menu
Jeżeli wszystko jest OK, po odświeżeniu panelu, w grupie „Wygląd” pojawi się nowa strona „Menu”.

Możemy tutaj dodać podstrony, poszczególne wpisy lub linki zewnętrzne. Jak widać edycja menu jest bardzo wygodna – za pomocą interakcji „przeciągnij i upuść” można zmieniać kolejność elementów a dodawanie i usuwanie ich działa asynchronicznie – bez odświeżania strony panelu.
Podsumowując, rejestracja co najmniej jednego menu pozwala uzyskać dostęp do strony z tymi ustawieniami a po kliknięciu w „Utwórz menu” będziemy mogli przypisać stworzone menu do zarejestrowanych i nazwanych obiektów:

Krok 3: Wyświetlanie menu w szablonie
Teraz musimy w szablonie wywołać funkcję drukującą menu. WordPress posiada wewnętrzną funkcję do realizacji tego celu:
wp_nav_menu(array("theme_location" => "header-menu"));
Taka funkcja umieszczona gdziekolwiek w szablonie wygeneruje nam gotowy kod HTML menu:
<div class="menu-menu-1-container"> <ul id="menu-menu-1" class="menu"> <li id="menu-item-204" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home current-menu-item page_item page-item-17 current_page_item menu-item-204"> <a href="http://localhost/" aria-current="page">Strona główna</a> </li> <li id="menu-item-205" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-205"> <a href="http://localhost/blog/">Blog</a> </li> <li id="menu-item-206" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-206"> <a href="http://localhost/kontakt/">Kontakt</a> </li> <li id="menu-item-208" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-208"> <a href="http://localhost/oferta/">Oferta</a> </li> </ul> </div>
Na tym możemy zakończyć oficjalną część tutorialu.
Zaawansowane programowanie menu WordPress
Za pomocą argumentów możemy dodawać klasy, otaczać elementy i linki niestandardowymi kawałkami kodu. Dla przykładu, możemy się pozbyć otaczającego diva:
wp_nav_menu(array( "theme_location" => "header-menu", "container" => "" ));
Załóżmy, że nasz szablon budujemy za pomocą Boostrapa i do głównego tagu ul chcemy dodać klasę navbar-nav. Nic prostszego:
"menu_class" => "navbar-nav"
Jak widać, funkcja umożliwia wygenerować kod według wymagań. Nie można jednak tak prostym sposobem dodać klasy do poszczególnych elementów <li>. Aby to osiągnąć mamy dwa wyjścia:
- stworzenie własnego argumentu za pomocą filtra,
- stworzyć własny „walker”,
- użyć funkcji wp_get_nav_menu_object(), za pomocą której zakodujemy całe menu od podstaw
Załóżmy, że do każdego elementu <li> chcemy dodać klasę nav-item a do każdego linku <a> nav-link.
Metoda 1: Filtry
Tworzymy funkcję, która będzie nam umożliwiać dodanie dodatkowego parametru my_menu_li_class:
function my_menu_li_class($classes, $item, $args) { if (property_exists($args, 'my_menu_li_class')) { $classes[] = $args->my_menu_li_class; } return $classes; } add_filter('nav_menu_css_class', 'my_menu_li_class', 1, 3);
oraz my_menu_a_class:
function my_menu_a_class( $attributes, $item, $args ) { if (property_exists($args, 'my_menu_a_class')) { $attributes['class'] = $args->my_menu_a_class; } return $attributes; } add_filter( 'nav_menu_link_attributes', 'my_menu_a_class', 1, 3 );
Teraz dodajemy stworzone przez nas parametry do funkcji wp_nav_menu:
'my_menu_li_class' => 'nav-item',
'my_menu_a_class' => 'nav-link'
Metoda 2: Rozszerzanie klasy Walker
Poprzednia metoda wymaga od nas znajomości filtrów i każdorazowej edycji parametrów. Alternatywnym rozwiązaniem jest rozszerzenie klasy Walker. Tworzymy klasę My_Walker która dziedziczy po klasie Walker:
class My_Walker extends Walker { var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' ); function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { $output .= sprintf( "\n<li class=\"nav-item\"><a class=\"nav-link\" href='%s'%s>%s</a></li>\n", $item->url, ( $item->object_id === get_the_ID() ) ? ' class="current"' : '', $item->title ); } }
Przy $output widać dodane przez nas klasy nav-item i nav-link. Teraz możemy specjalnym parametrem odnieść się do Walkera:
"walker" => new My_Walker()
Jeżeli nie wiesz co oznacza dziedziczenie, zapraszam do kursu obiektowego PHP od podstaw.
Metoda 3: Generowanie własnego kodu
Możemy też bez wspierania się gotowymi funkcjami wygenerować cały kod dynamicznego menu. To najbardziej hardkorowa metoda, ale dająca najwięcej możliwości i zwalniająca nas z używania wbudowanych w WordPressa funkcji i filtrów, których używanie – przynajmniej według mnie – może się stać męczące.
Za pomocą funkcji wp_get_nav_menu_object oraz wp_get_nav_menu_items możemy otrzymać wszystko co jest możliwe do odczytania z obiektu menu:
$menu_name = "header-menu"; if (($locations = get_nav_menu_locations()) && isset($locations[$menu_name])) { $menu = wp_get_nav_menu_object($locations[$menu_name]); $menu_items = wp_get_nav_menu_items($menu->term_id); var_dump($menu_items); }
Teraz za pomocą pętli foreach możemy iterować po elementach i generować kod HTML menu:
$html = ""; foreach ((array) $menu_items as $key => $menu_item) { $title = $menu_item->title; $url = $menu_item->url; $html .= <li><a href="$url">$title</a></li> }
Advanced Custom Fields (ACF) w Menu WordPress
Taka metoda generowania dynamicznego menu może być potrzebna w przypadku kiedy korzystamy z niestandardowych pól ACF. Załóżmy, że chcemy mieć możliwość kolorowania każdego elementu menu lub dodać do elementów menu tła graficzne – wystarczy stworzyć pole ACF, przypisać go do menu i wtedy takie wartości można otrzymać wewnątrz foreach za pomocą:
$color = get_field("color", $menu_item);
Jeżeli chcemy dodać ikony do pozycji menu, można użyć filtra zaprezentowanego w dokumentacji ACF:
function my_wp_nav_menu_icons( $items, $args ) { foreach( $items as &$item ) { $icon = get_field('icon', $item); if( $icon ) { $item->title .= ' <i class="fa fa-'.$icon.'"></i>'; } } return $items; } add_filter('wp_nav_menu_objects', 'my_wp_nav_menu_icons', 10, 2);
Implementacja menu Bootstrap
Klasy z tego frameworka podałem jako przykład. Oczywiście, nie trzeba samemu implementować całej struktury nawigacji Bootstrapa, ponieważ w sieci są opublikowane gotowe rozszerzenia klasy Walker dla tak popularnych bibliotek.
Jedną z nich jest: https://github.com/wp-bootstrap/wp-bootstrap-navwalker
Wystarczy dodać do folderu z motywem plik class-wp-bootstrap-navwalker.php dołączyć go do functions.php
function register_navwalker(){
require_once get_template_directory() . '/class-wp-bootstrap-navwalker.php';
}
add_action( 'after_setup_theme', 'register_navwalker' );
W argumentach naszego menu dodajemy wtedy tylko:
'fallback_cb' => 'WP_Bootstrap_Navwalker::fallback',
'walker' => new WP_Bootstrap_Navwalker(),
Jeżeli używamy Bootstrapa w wersji 5. W kodzie trzeba zmienić atrybut data-toggle na data-bs-toggle. Można to zrobić za pomocą ręcznej edycji klasy bądź eleganckiego filtra:
add_filter( 'nav_menu_link_attributes', 'bootstrap5_dropdown_compatiblity' ); function bootstrap5_dropdown_compatiblity( $atts ) { if ( array_key_exists( 'data-toggle', $atts ) ) { unset( $atts['data-toggle'] ); $atts['data-bs-toggle'] = 'dropdown'; } return $atts; }
Ukryte pola elementów menu
Na koniec jeszcze pokażę małą ciekawostkę związaną z dodatkowymi opcjami jakie możemy wykorzystać z poziomu panelu WordPress. Pozostając cały czas na podstronie Menu, w Opcjach Ekranu, które zazwyczaj można rozwinąć u góry po prawej stronie panelu możemy włączyć dodatkowe pola dla elementów menu:

Od teraz dla każdego elementu menu będziemy mieli do dyspozycji dodatkowe pola.

- Tytuł czyli atrybut title,
- Klasę CSS, która jest dodawana do elementu li
- Relację XFN czyli atrybut rel
- Opis – dodatkową treść, którą można zaprezentować dla elementu menu
Podsumowanie
Jak widać w WordPressie mamy bardzo wiele narzędzi, które udostępniają praktycznie nieograniczone możliwości dostosowania kodu HTML całej struktury menu do naszych potrzeb. Dynamiczne menu, którym łatwo może zarządzać użytkownik to bardzo przydatny element strony WordPress.
Za pomocą menu i zagnieżdżania elementów możemy tworzyć najbardziej skomplikowane struktury a za pomocą wbudowanych funkcji i metod które zaprezentowałem w tym artykule, możemy dowolnie dostosowywać wygenerowany kod HTML dokładnie tak jak tego chcemy.
Źródła:
- https://developer.wordpress.org/reference/functions/wp_nav_menu/
- https://developer.wordpress.org/reference/functions/wp_get_nav_menu_object/
- https://developer.wordpress.org/reference/functions/wp_get_nav_menu_items/
Odpowiedz Anuluj odpowiedź