Programmierung

WordPress: Wirklich individuelle Navigation erstellen und der Walker_Nav_Menu Klasse

2 Minuten Lesezeit

Dieser Beitrag ist von August 2012. Die Screenshots zeigen die Oberfläche von damals, heute sieht sie teils etwas anders aus.

Es kommt immer wieder vor, dass eine Website-Navigation, nicht nur den Seitennamen anzeigen soll, sondern auch Informationen, die dazu gehören, wie zum Beispiel die Description oder das Seiten-Bild, oder was auch immer… Um die Kontrolle darüber zu bekommen, braucht man die Walker_Nav_Menu Klasse.

Vorgehensweise
In der functions.php folgenden Code eingeben, es entspricht dem WP-eigenen Code. Dort werden anschließend die gewünschten Änderungen durchgeführt.

class Custom_Walker extends Walker_Nav_Menu{

  function start_el(&$output, $item, $depth, $args){
    
    $classes = empty ( $item->classes ) ? array () : (array) $item->classes;
    $class_names = join(" ", apply_filters("nav_menu_css_class", array_filter($classes), $item));

    ! empty ($class_names) and $class_names = " class='" . esc_attr($class_names) . "'";

    $output .= $indent . "<li id='menu-item-" . $item->ID . "'" . $value . $class_names . ">";

    $attributes = "";

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

    $title = apply_filters("the_title", $item->title, $item->ID);

    $item_output = $args->before . "<a $attributes>" . $args->link_before . $title . "</a> " . $args->link_after. $args->after;

    // Since $output is called by reference we don't need to return anything.
    $output .= apply_filters("walker_nav_menu_start_el", $item_output, $item, $depth, $args);
  }
}

Was wollen wir jetzt ändern? Zum Beispiel keine <ul><li>-Navigation sondern einfach <div> für die einzelnen Navigationselemente. Dazu das Artikelbild unterhalb, und die Description (aus dem Menue). Das sieht dann z. B. aus aus:

// Add these lines in order to fetch the additional information you wish to display

// We need the target page id in order to fetch the page image
$page = get_page_by_path(basename($item->url));
$page_id = $page->ID;
// We should check if there is an image set or not, but we are lazy for this example
$image_url = get_the_post_thumbnail( $page_id, 'custom-image-preview' );
// Same thing for the description
$description = esc_attr( $item->description );

// Remove the li
// Instead of $item_output = $args->before . "<a $attributes>" . $args->link_before . $title . "</a> " . $args->link_after. $args->after;
$output .= "";

// Change the output like you need it
$item_output = $args->before . "<div class='container-main'><a $attributes>" . $args->link_before . $title . "</a><div class='page-image'>" . $image_url . "</div><div class='menu-page-description'>" . $description . "</div></div> " . $args->link_after. $args->after;

Damit es nun auch angezeigt wird, muss der Aufruf von wp_nav_menu modifiziert werden. Beispielsweise so:

wp_nav_menu( array( 'theme_location' => 'my-custom-navigation', 
    'menu' => '', 
    'container' => 'nav', // Auto wrap navigation in <nav> area
    'container_class' => FALSE, 
    'container_id' => FALSE, 
    'menu_class' => FALSE, 
    'menu_id' => FALSE, 
    'echo' => true, 
    'fallback_cb' => 'wp_page_menu', 
    'before' => '', 
    'after' => '', 
    'link_before' => '', 
    'link_after' => '', 
    'items_wrap' => '%3$s', // Remove the ul container
    'depth' => 0, 
    'walker' => new Custom_Walker ) );