Individualisierung von Navigationsmenüs in WordPress

Naviation mit Untertitel
Ich habe mich dieses Wochenende mit Regular Expressions beschäftigt, nachdem ich im Laufe meines Lernprozesses immer wieder darauf gestoßen bin, mit dem wilden Durcheinander zwischen den Schrägstrichen aber nie etwas anfangen konnte. Leuten, denen es auch so geht, und die ein paar Minuten Zeit haben sich diesem Kapitel zu nähern, kann hierzu wärmstens die Reihe Regular Expression for Dummies empfehlen, die es sehr verständlich vermittelt.

Bei Smashing Magazine gibt es eine schöne Übersicht über Trends bei der Gestaltung von Naviationsleisten und mir gefiel für eines meiner Projekte die Herangehensweise von Intereactive.net sehr gut. Ich hab mir also überlegt, so etwas ähnliches auch zu probieren und erklärende oder handlungsauffordernde Untertitel hinzuzufügen.

Mit wp_list_pages() ermöglicht uns WordPress dynamisch eine Liste der vorhanden Seiten zu generieren und gibt uns sogar noch die Möglichkeit Bedingungen und Zusätze mitzuliefern. Diese Herrlichkeit endet jedoch recht schnell, weil nur ein Array mit Strings oder ein String übergeben werden können, keine multidimensionalen Arrays – geschweige denn PHP-Funktionen. Die Lösung für dieses Problem finden wir bei den Filtern, in die uns WordPress einhaken lässt, genauer gesagt im gleichnamigen wp_list_pages-Filter.

Um also dynamischen Inhalt in die Liste einzufügen, schnappen wir uns den HTML-String bevor er an den Browser ausgegeben wird mittels der add_filter() Funktion und fügen an einer von uns bestimmten Stelle den gewünschten Inhalt ein, den wir per ‚Benutzerdefiniertes Feld‘ vorher bestimmt haben. Hört sich einfach an. Und ist es eigentlich auch wenn man weiß wie’s geht, oder (wie ich) Zeit zum probieren hat.

Zuerst gehen wir in den Adminbereich unserer WordPress Installation und fügen bei jeder Seite, die in der Navigation einen Untertitel erhalten soll, ein Benutzerdefiniertes Feld ein. Ich habe mich für ’subtitle‘ als Feldname entschieden und als Wert jeweils einen Einzeiler geschrieben.

Als nächstes gehen wir in unser Theme und schauen im Template nach der Funktion wp_list_pages(). Da ich eine Seitennavigation baue, schaue ich in der sidebar.php. Ich füge dann in das Array mit den Übergabewerten das Stück HTML hinzu, in das später der dynamische Inhalt eingebettet wird.

wp_list_pages(array(
    'title_li' => 0,
    'depth' => 1,
    'link_after' => '<span class="linkText">stringToReplace&nbsp;</span>'
));

Ich habe nach ’stringToReplace‘ noch ein non-breaking space eingefügt, um das <span>-Tag nicht leer zu lassen, falls eine Seite mal keinen Untertitel definiert haben sollte, und dann unter unterschiedlichen Höhen der Anchors zu leiden.

Danach befassen wir uns mit der functions.php unseres Themes, hier muss nämlich der Filter rein, sowie die Funktion, mit der wir die Navigation beeinflussen. Ich zeige euch zunächst den Code und gehen dann Schritt für Schritt auf das ein, was da passiert.

add_filter('wp_list_pages','enhance_list');

function enhance_list( $content ) {

    preg_match_all('/page-item-(d+)/',$content,$matches);

    $string = str_replace('</li>','</li>|',$content);
    $strings = explode('|',$string);

    for($i=0;$i<count($matches[1]);$i++){
        $strings[$i] = str_replace('stringToReplace',get_post_meta($matches[1][$i], 'subtitle', true),$strings[$i]);
    }

    $content = implode($strings);
    return $content;
}

Zunächst setzen wir den Filter und sagen ihm welche Funktion er zwischenzuschalten hat. Danach erstellen wir die Funktion, der der Ausgabestring übergeben wird ($content).

Und hier kommt auch schon einer der Gründe, warum ich mich dieses Wochende mit Regular Expressions beschäftigt habe: Wir suchen nach den Page-IDs in den CSS-KLassen. wp_list_pages() stattes jedes <li>-Tag nämlich mit den CSS-Klassen list-item und list-item-Page-ID aus, so können wir die mit preg_match_all() schön rausholen.

Da wir unterschiedliche Feld-Werte als Untertitel haben, aber nur einen zu ersetzenden Wert der Seitenauflistung weitergeben können, müssen wir den übergebenen HTML-String wieder in seine Seiten-Bestandteile aufteilen. Ich habe dazu einfach nach jedem schließenden <li>-Tag einen |-Separator eingefügt und den String danach an diesen Separatoren unterteilt (Wenn ihr eine bessere Lösung habt, lasst sie mich in der Kommentar-Sektion wissen). So haben wir zwei Arrays, eines mit den Page-IDs und eines mit den List-Items, mit denen wir nun arbeiten können.

Mit einer For-Schleife laufen wir durch die zwei Arrays und ersetzen den vordefinierten Token (hier: ’stringToReplace‘) mit dem Feld-Wert, den uns die Funktion get_post_meta() liefert.

Zu guter Letzt fügen wir das Array mittels implode() wieder zu einem String zusammen und geben diesen zurück.

Fertig!

Das schöne an dem Ganzen ist, dass so nur jene Listen beeinflusst werden, bei denen wir den ’stringToReplace‘ definiert haben, da str_replace() nichts ersetzt wenn es den zu ersetzenden String nicht findet. So können wir die wp_list_pages()-Funktion auch noch an verschiedenen anderen Stellen auf der Seite einsetzen (z.B. im Footer), ohne dass die ursprünliche Formatierung darunter leidet, obwohl wir ja jeden Aufruf der Funktion filtern.

4 Gedanken zu „Individualisierung von Navigationsmenüs in WordPress

  1. Hallo,
    hat mir super geholfen, vielen Dank. Ich habe noch exclude hinzugefügt, aber leider weiß ich nicht wie ich mehrere Seiten ausschliessen kann. Es funktioniert nur bei einer, welchen Trennzeichen muss ich verwenden? Vielen Dank!

  2. Danke für den Tipp, war schon am überlegen doch nen Statisches Menü machen zu müssen. Auf den Gedanken mit dem Benutzerdefinierten Feld war ich zwar gekommen aber nicht wie ich es ausserhalb des Posts nutzen konnte. Gute Arbeit!

  3. DANKE! Konnte mit dem ein oder anderen Denkanstoss aus deinem Post die folgende Funktion entwickeln.

    Mit Filtern wäre die Sache sicherlich schöner, effektiv ist es aber allemal, um ein Array bestehend aus Link und ID des jeweiligen Posts zu generieren, Anhand der IDs konnte ich im nachfolgenden Schritt wunderbar auf Submenüs überprüfen und ggf. anhöngen:

    function buildarray($string) {
    	$string = str_replace('','|',$string); // an jedes listelement ein trennzeichen anhängen
    	$array = explode('|', $string); //anhand der trennzeichen array erstellen
    	unset($array[(count($array))-1]); //letztes (leeres) element löschen
    				
    	$content_and_ids = array(); // rückgabearray erstellen
    	foreach($array as $element) { 
    		preg_match('(page-item-.[0-9]*)',$element, $page_id); //string der auf jeden fall die oage-id enthält rausparsen
    		$page_id = implode(preg_replace('([^0-9]*)','',$page_id)); //alles bis auf die id entfernen und als string ausgeben
    		$newentry = array("ID" => $page_id, "LINK" => $element); //zweite array-dimension erstellen und mit der id sowie dem alten link befüllen
    		array_push($content_and_ids,$newentry); //rückgabearray befüllen
    	}
    	return $content_and_ids;
    }
    
    echo buildarray(wp_list_pages('echo=0&title_li='));
    

Kommentare sind geschlossen.