publikacja: 10 października 2012, autor: , komentarzy 8 https://wpninja.pl/artykuly/menu-wordpress-3-tworzenie-rozszerzenia-klasy-walker/

Menu WordPress #3 – tworzenie rozszerzenia klasy Walker

Menu WordPress #3 – tworzenie rozszerzenia klasy Walker

WordPress oferuje kilka sposobów ingerencji w kod HTML menu, ale największy poziom kontroli można osiągnąć rozszerzając klasę Walker. Dzięki temu, zamiast tworzyć logikę niezbędną do poruszania się po „drzewku” elementów będziesz mógł skupić się na wynikowym kodzie HTML. Na szczęście nie jest to tak trudne, jak mogło by się wydawać.

Czym jest klasa Walker?

Klasa Walker pozwala na poruszanie się po danych o strukturze hierarchicznej. W WordPressie mamy do czynienia z tego typu danymi na przykład w przypadku kategorii, komentarzy czy stron. Walker jest klasą abstrakcyjną, co oznacza że nie korzysta się z niej bezpośrednio, ale należy ją odpowiednio rozszerzyć.

Rozszerzenia

WordPress posiada kilka wbudowanych rozszerzeń klasy Walker. Każda z nich tworzy kod HTML niezbędny do wyświetlenia odpowiednich elementów strony:

  • Walker_Nav_Menu – menu,
  • Walker_Page – lista stron,
  • Walker_PageDropdown – rozwijana lista stron,
  • Walker_Category – lista kategorii,
  • Walker_CategoryDropdown – rozwijana lista kategorii,
  • Walker_Comment – lista komentarzy.

Metody

Przyjrzyjmy się teraz bliżej metodom, jakie oferuje klasa Walker:

  • walk:
    jest to metoda która zwraca wygenerowany kod HTML. Funkcja „przechodzi” przez wszystkie elementy i wywołuje funkcje start/end_lvl oraz start/end_el, które generują właściwe tagi HTML w zależności od umiejscowienia elementu w strukturze;
  • start_lvl:
    generuje otwierający znacznik HTML elementu, który będzie zawierał elementy potomne
    (tag <ul> dla menu);
  • end_lvl:
    generuje zamykający znacznik HTML elementu, który zawiera elementy potomne
    (tag </ul> dla menu);
  • start_el:
    generuje otwierający znacznik HTML elementu
    (tag <li> oraz cały <a> dla menu);
  • end_el:
    generuje zamykający znacznik HTML elementu
    (tag </li> dla menu).

Tworząc własne rozszerzenie klasy Walker, nie musimy nadpisywać wszystkich wymienionych powyżej metod, a jedynie te, które generują interesujące nas elementy.

Tyle w kwestii wstępu, teraz czas na praktykę.

Tworzenie menu z opisami

W tym przykładzie stworzymy własne rozszerzenie klasy Walker_Nav_Menu, dzięki któremu dla elementów menu najwyższego poziomu, obok tytułu wyświetlimy również opis.

Menu z opisami

Menu z opisami

Krok 1: Przygotowania

Zanim przejdziemy do pisania kodu, musimy zarejestrować nowy obszar menu a następnie stworzyć odpowiednie menu w panelu administratora.

Aby zarejestrować nowe menu, musimy wstawić następujący fragment kodu do pliku functions.php:

register_nav_menus( array(
   'primary-menu' => __('Menu główne'),
) );

Teraz możemy przejść do zakładki „Wygląd / Menu” w panelu administracyjnym. Klikając „Opcje ekranu” w górnym prawym rogu strony możemy zaznaczyć, aby przy każdym elemencie były wyświetlane dodatkowe pola. W naszym przykładzie potrzebujemy wypełnić również pole „Opis”, które domyślnie jest ukryte:

Tworzenie menu w panelu administracyjnym

Tworzenie menu w panelu administracyjnym

Po zapisaniu menu musimy pamiętać o przypisaniu go do właściwego obszaru w szablonie.

Krok 2: Rozszerzanie klasy Walker

Spójrzmy na docelową strukturę kodu HTML:

<ul>
   <li><a href=”#”>Strona główna<em>...zacznij tutaj!</em></a></li>
   <li><a href=”#”>Oferta<em>...co możemy dla Ciebie zrobić?</em></a></li>
   <li><a href=”#”>Portfolio<em>...nasze realizacje!</em></a></li>
   <li><a href=”#”>Kontakt<em>...napisz do nas!</em></a></li>
</ul>

Opis elementu menu powinien pojawić się w środku elementu <a>, tuż po nazwie.

Wcześniej wspominałam, że rozszerzając klasę Walker nie ma potrzeby nadpisywania wszystkich dostępnych metod, możemy ograniczyć się do jednej wybranej metody. W tym przypadku potrzebujemy zmodyfikować tylko metodę start_el, która odpowiada ze wyświetlenie otwierającego tagu <li> oraz linka elementu menu.

Poniższy kod powinien się naleźć w pliku functions.php:

class Description_Walker extends Walker_Nav_Menu{
   ...
}

Ciało klasy Description_Walker będzie bazować na klasie Walker_Nav_Menu, znajdującej się w pliku nav-menu-template.php. Aby ułatwić sobie zadanie i zapewnić poprawność kodu, skopiowałam całą funkcję start_el z powyższego pliku (samego pliku nie należy zmieniać, gdyż należy on do core WordPressa), a następnie dokonałam w jej kodzie odpowiednich modyfikacji:

class Description_Walker extends Walker_Nav_Menu{

   function start_el(&$output, $item, $depth, $args) {

      global $wp_query;
      $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
      
      $class_names = $value = '';
      $classes = empty( $item->classes ) ? array() : (array) $item->classes;
      $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
      $class_names = ' class="'. esc_attr( $class_names ) . '"';
      $output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';

      $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
      $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
      $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
      $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';

      if ($depth == 0) {
         $description = ! empty( $item->description ) ? '<em>' . esc_attr( $item->description ).'</em>' : '';
      } else {
         $description = "";
      }

      $item_output = $args->before;
      $item_output .= '<a'. $attributes .'>';
      $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID );
      $item_output .= $description.$args->link_after;
      $item_output .= '</a>';
      $item_output .= $args->after;

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

}

W linijce 16 za pomocą zmiennej $depth, sprawdzamy czy jesteśmy na najwyższym poziomie menu (wartość zmiennej $depth wynosi zero) i w zależności od wyniku ustawiamy wartość zmiennej $description. Następnie w linijce 25 dołączamy opis do wynikowego kodu HTML.

Krok 3: Wyświetlanie menu

Po wykonaniu tego kroku możemy już wyświetlić nasze menu wywołując funkcję wp_nav_menu w odpowiednim miejscu w szablonie, na przykład w pliku header.php, za pomocą następującego fragmentu kodu:

<?php wp_nav_menu( array('theme_location'=>'primary-menu','walker' => new Description_Walker())); ?>

Walker jest jednym z parametrów funkcji wp_nav_menu. Jako jego wartość podajemy nazwę jaką nadaliśmy naszemu rozszerzeniu klasy Walker. Należy również pamiętać, aby w parametrze ‘theme_location’ podać prawidłową nazwę menu, które zdefiniowaliśmy w pierwszym kroku za pomocą funkcji register_nav_menus.

Podsumowanie

Mam nadzieję, że ten artykuł przybliżył Wam klasę Walker i wytłumaczył sposób jej działania. Menu jest tylko jednym z przykładów zastosowania tego rozwiązania. Warto pamiętać o tym również wtedy, gdy będziemy mieli do czynienia z kategoriami czy komentarzami.

Jeśli mimo wszystko nie czujesz się na siłach, aby napisać własne rozszerzenie klasy Walker, to w sieci możesz znaleźć gotowe rozwiązania np. na menu obrazkowe lub menu z nieklikalnym rodzicem.

Komentarze

  1. Menu WordPress #2 – własna struktura HTML | WPNinja 12 lat temu:

    […] budowy menu w oparciu o listę nieuporządkowaną <ul>.W kolejnym artykule przedstawię Wam klasę Walker oraz pokażę jej zastosowanie w praktyce. Podobał się artykuł? Dodaj kanał RSS / Atom do swojego czytnika lub zapisz się na bezpłatny […]

    odpowiedz
  2. Menu WordPress – zarządzanie identyfikatorami i klasami | WPNinja 12 lat temu:

    […] Wam, w jaki sposób wygenerować menu z własną strukturą kodu HTML, bez konieczności pisania rozszerzenia klasy Walker. Podobał się artykuł? Dodaj kanał RSS / Atom do swojego czytnika lub zapisz się na bezpłatny […]

    odpowiedz
  3. Alicja 12 lat temu:

    Dziękuję bardzo za ten tutorial… czegoś takiego właśnie szukałam od pewnego czasu :)

    odpowiedz
  4. Kamil 10 lat temu:

    Dzięki wielki – za ten artykuł. Dopiero zaczynam przygodę z WP, ale planuję duży serwis a tego typu rozwiązania na pewno się przydadzą.

    P.S. Może tak artykuł o różnych klasach dla poszczególnych kategorii – tak aby na stronie głównej elementy przy danym artykule miały inne kolory – np dla kategorii A – elementy są niebieskie – dla kategorii B elementy są zielone :)

    odpowiedz
    1. Paweł Knapek 10 lat temu:

      @Kamil, w tym akurat wielkiej filozofii nie ma.
      https://codex.wordpress.org/Function_Reference/body_class i formatujesz elementy w odniesieniu do body.

      odpowiedz
  5. Kamil 10 lat temu:

    Fajny tutorial, trochę wyjaśnił walkera.

    odpowiedz
  6. Marek 5 lat temu:

    Kod walkera nie działa (wordpress zwraca błędy), ale sam artykuł spoko :-)

    odpowiedz
    1. Marek 5 lat temu:

      Eee… po prostu mam nowszą wersję wp niż we wpisie… Sorry za lamerski komentarz.

      odpowiedz

Dodaj własny komentarz


Warning: Undefined variable $user_ID in /home/klient.dhosting.pl/wpn/wpninja.pl/public_html/wp-content/themes/wpninja/comments.php on line 95

Odnośniki z innych stron

Lista innych stron, które w jakiś sposób odnoszą się do opublikowanej tutaj treści:

  1. Menu WordPress #2 – własna struktura HTML | WPNinja

    […] budowy menu w oparciu o listę nieuporządkowaną <ul>.W kolejnym artykule przedstawię Wam klasę Walker oraz pokażę jej zastosowanie w praktyce. Podobał się artykuł? Dodaj kanał RSS / Atom do swojego czytnika lub zapisz się na bezpłatny […]

  2. Menu WordPress – zarządzanie identyfikatorami i klasami | WPNinja

    […] Wam, w jaki sposób wygenerować menu z własną strukturą kodu HTML, bez konieczności pisania rozszerzenia klasy Walker. Podobał się artykuł? Dodaj kanał RSS / Atom do swojego czytnika lub zapisz się na bezpłatny […]