WordPress: Automatisch Links ins Menü einbauen
09.08.2012 in: Webdesign und WordPress
Wollen wir einem Navigationsmenü einen Link hinzufügen, so bietet sich uns der Filter wp_nav_menu_objects
an. Er wird von der Funktion wp_nav_menu()
gestellt, unmittelbar bevor der Walker auf die Links zugreift und sie formatiert.
Wir bekommen zwei Argumente: $sorted_menu_items und $args. Das erste ist ein Array der Links, das zweite enthält die Argumente, mit denen wp_nav_menu()
aufgerufen wurde. Diese Argumente können wir um eigene erweitern.
Zwei Beispiele sollen das verdeutlichen.
An- und Abmeldelink einbauen
Aufgabe: Wir wollen einen Link zum An- oder Abmelden ans Menü anhängen. Allerdings nicht an alle Menüs, sondern nur an ein ausgewähltes. Die ursprüngliche Frage hierzu steht auf WordPress Stack Exchange.
Denken wir uns zunächst ein zusätzliches Argument für das Menü aus, mit dem wir es als erweiterbar kennzeichnen:
// If there is no menu assigned we show nothing. has_nav_menu('top-menu'
) and wp_nav_menu( array ('theme_location'
=>'top-menu'
,'add_loginout'
=> TRUE ) );
Hier rufen wir ein Menü auf, das wir in der functions.php
etwa so registriert haben:
register_nav_menu('top-menu'
, __('Menu at the top of the page.'
,'t5_theme'
) );
Der Parameter add_loginout
sei unser Kennzeichen dafür, daß wir einen speziellen Link haben möchten. Dazu registrieren wir eine Filterfunktion, die mit normaler Priorität 10
läuft und zwei Argumente erwartet:
add_filter('wp_nav_menu_objects'
,'t5_menu_log_link'
, 10, 2 );
In der Funktion t5_menu_log_link()
prüfen wir, ob das Argument add_loginout
gesetzt wurde und ob es zu TRUE
evaluiert (empty
erledigt beides auf einmal). Je nach Status des aktuellen Besuchers hängen wir dann einen passenden Link an. Dieser Link ist eine Objektinstanz der Klasse stdClass
mit bestimmten notwendigen Eigenschaften.
/** * Add a link to the nav menu. * * @wp-hook wp_nav_menu_objects * @param array $sorted_menu_items Existing nav menu items * @param object $args Nav menu arguments. 'add_loginout' must be TRUE * @return array Nav menu items */ function t5_menu_log_link( $sorted_menu_items, $args ) { // Parameter missing or set to FALSE if ( empty ( $args->add_loginout ) ) { return $sorted_menu_items; } $is_in = is_user_logged_in(); $link = new stdClass; $link->title = __( $is_in ?'Log Out'
:'Log In'
); $link->menu_item_parent = 0; $link->ID =''
; $link->db_id =''
; $link->url = $is_in ? wp_logout_url() : wp_login_url(); $sorted_menu_items[] = $link; return $sorted_menu_items; }
Das Ergebnis zeigt dieser Screenshot:
Im hinteren Tab bin ich angemeldet, der vordere Tab ist ein privater, in dem ich abgemeldet bin. Das ist übrigens ein schönes Feature aktueller Browser, das einem das Testen beider Zustände parallel sehr erleichtert.
Wir können auch einen Link anhängen, dessen Titel und Adresse wir jetzt noch gar nicht kennen:
Letzten Blogartikel anhängen
Aufgabe: Der letzte Blogbeitrag soll ein eigener Menüpunkt werden. Wir wollen außerdem einen Auszug ins title
-Attribut setzen und den Link mit einer zusätzlichen CSS-Klasse versehen. Ursprung wieder auf WordPress Stack Exchange.
Als kennzeichnendes Argument für wp_nav_menu()
wählen wir jetzt add_latest_post
; der Einsatz sollte inzwischen klar sein, also lasse ich den aufrufenden Code mal weg und springe gleich zur Filterfunktion.
add_filter('wp_nav_menu_objects'
,'t5_latest_post_in_nav_menu'
, 10, 2 ); /** * Add a link to the latest post to the nav menu. * * @wp-hook wp_nav_menu_objects * @param array $sorted_menu_items Existing menu items * @param object $args Nav menu arguments as object. * @return array */ function t5_latest_post_in_nav_menu( $sorted_menu_items, $args ) { if ( empty ( $args->add_latest_post ) or ! $latest = get_posts( array ('numberposts'
=> 1 ) ) ) { return $sorted_menu_items; } $post = $latest[0]; $content = empty ( $post->post_excerpt ) ? $post->post_content : $post->post_excerpt; $link = array ('title'
=> esc_html( $post->post_title ),'menu_item_parent'
=> 0,'ID'
=>''
,'db_id'
=>''
,'url'
=> get_permalink( $post->ID ),'classes'
=> array ( 0 =>''
, 1 =>'menu-item'
, 2 =>'menu-item-type-post_type'
, 3 =>'menu-item-object-post'
, 4 =>'latest-post'
, // special class ), // strips all tags and reduces the length to 20 words'attr_title'
=> wp_trim_words( $content, 20 ), ); $sorted_menu_items[] = (object) $link; return $sorted_menu_items; }
Was passiert hier?
- Wir prüfen, ob der Parameter
add_latest_post
zuTRUE
evaluiert und ob wir einen Beitrag gefunden haben. Klappt eines von beiden nicht, steigen wir sofort aus. - Wir merken uns den Auszug (so vorhanden) oder den Beitragsinhalt.
- Wir bauen den Link diesmal als Array, einfach um eine alternative Schreibweise vorzustellen.
- Wir maskieren den Post-Titel, denn der darf in WordPress durchaus Markup enthalten. Das können wir im Menü aber nicht gebrauchen.
- Dann setzen wir ein paar notwendige Attribute, die hier nicht wichtig sind. Über
menu_item_parent
könnten wir beispielsweise einen Menüpunkt auswählen, dem unser Link untergeordnet wird. Aber wir wollen ihn ja nicht verstecken … - Als URL nehmen wir den Permalink des Beitrages.
- In
classes
setzen wir die CSS-Klassen, die unser Link erhalten soll. Über die neue Klasselatest-post
können wir den Link später im Stylesheet ansprechen. - Von
wp_trim_words()
lassen wir jetzt alles Markup und alle Zeilenumbrüche aus $content entfernen, außerdem reduzieren wir dessen Länge auf 20 Worte. Das wird schließlich eintitle
-Attribut, kein Roman. - Und zuletzt konvertieren wir den Array in ein Objekt, das wir an $sorted_menu_items anhängen, ehe wir es WordPress wieder in die Hand drücken.
Ergebnis: