geschrieben von Micha am 01. Januar 2010 | 12 Kommentare
Wer WordPress für Firmenwebseiten einsetzt, hat meistens mit statischen Seiten zu tun, die in einem Hierarchie-Baum abgelegt sind. Um diese Seiten für den Nutzer erreichbar zu machen, gibt es viele Möglichkeiten.
In diesem Beitrag möchte ich ein Beispiel zeigen, in dem sich die Hauptseiten in einer horizontalen Navigation befinden. Die jeweiligen Unterseiten werden beim Klick auf die Hauptseite in der Sidebar angezeigt.
Zum besseren Verständnis nehmen wir folgende Seiten-Struktur:
Home
Software
Bildbearbeitung
Adobe Photoshop
Gimp
Content Managment Systeme
WordPress
Drupal
Joomla
Hardware
About us
Die Seiten Home, Software, Hardware und About us befinden sich in der horizonatlen Navigation. Wenn der Nutzer beispielsweise auf Software klickt, sollen in der Sidebar alle Unterseiten von Software angezeigt werden.
WorPress stellt für solche Aufgaben den Template Tag wp_list_pages() mit zahlreichen Parametern zur Verfügung. Da wir aber nicht alle Seiten angezeigt haben wollen, ist für uns der Parameter child_of interessant. Der Parameter child_of gefolgt von einer ID listet alle Unterseiten eben dieser Seite, wenn welche vorhanden sind.
Jetzt kommen wir zum eigentlichen Problem. Klickt man jetzt auf Content Managment Systeme in der Sidebar, erscheinen nur noch die Seiten WordPress, Drupal und Joomla. Die Übergeordneten Seiten sind weg. Logisch, es werden ja nur die Kinder der aktuellen Seite angezeigt und die ist Content Managment Systeme. Für unser Problem brauchen wir aber immer die oberste Seite. Auch da hilft WordPress weiter. Es gibt eine Funktion get_post_ancestors, die alle übergeordneten Seiten in einem Array zurückliefert. Probiert mal folgendes aus:
<?php$my_page= get_the_ID();$anchestors= get_post_ancestors($my_page);var_dump($anchestors);// Klick auf Softwarearray(0){}// Klick auf Content Managnet Systemearray(1){[0]=> string(2)"63"}// 63 ist die ID von Software// Klick auf WordPressarray(2){[0]=> string(2)"65"[1]=> string(2)"63"}// 65 ist die ID von WordPress?>
Das würde immer so weitergehen, je tiefer die Hierarchie verschachtelt ist. Wichtig für uns sind 2 Sachen: die oberste Seite steht immer am Ende des Arrays und es kann ein leeres Array zurück kommen. Also gehen wir einfach an das Ende des Arrays und für den Fall, das es keine übergeordnete Seite gibt, geben wir alle Unterseiten dieser Seite aus. Dazu schreiben wir eine Funktion in unserer functions.php, da sie dort einfacher zu pflegen ist und auch in mehreren Sidebars verwendet werden kann:
function wpe_highest_ancestor(){global$post;$page_ancestors=end($post->ancestors);if(!empty($page_ancestors)){$child_of=$page_ancestors;}else{$child_of=$post->ID;}return$child_of;}
bisher hatte ich für jede “statische” Hauptseite mit ihren Unterseiten eine eigene Sidebar eingebunden.
Deine Lösung ist deutlich eleganter. Ich werde sie mal mit der Testinstallation ausprobieren. Wenn es klappt, ersetzt sie meine bisherige Krückenlösung.
Danke Dieter und ebenfalls ein gesundes Neues Jahr!
Eventuell mußt du Das Markup ändern, je nachdem, wie deine Sidebar aufgebaut ist. Aber das sollte für dich kein Problem darstellen.
Ohweh, das hab ich schon ewig gesucht, bisher hab ich die Kinder immer per CSS ausgeblendet (Äusserst umständlich bei starker Verschachtelung…). Vielen Dank, und schönes Neues!
Vielen Dank für den Hinweis mit get_post_ancestors.
Hast Du noch einen Tipp, für folgendes Problem? Um in Deinem Beispiel zu bleiben, möchte ich bei einem Click auf CMS, soll ab CMS der gesamte Subbaum angezeigt werden, aber ohne “Eltern” oder “SChwestern” von CMS.
Eine Beschreibung meiner Frage findest auch im Wordpress-Forum
Da Dirnbocher: Wenn ich dich richtig verstanden habe, mußt du meine Funktion verwenden, aber ohne array_reverse. Dann ist $page_ancestors[0] die nächst übergeordnete Seite. Probiers mal.
function wpe_highest_ancestor(){
global $post;
$page_ancestors = get_post_ancestors($post->ID);
if(!empty($page_ancestors[0])){
$child_of = $page_ancestors[0];
}else{
$child_of = $post->ID;
}
return (int) $child_of;
}
Hi Micha, das klang -für mich – doch etwas einfacher als ich das raff.
Kurzfassung: ich bekomme es nicht hin.
Dein 2. Codeblock; sehe ich das richtig, dass der a: in die sidebar muss, und b: dass ich die ids alle manuell anfassen muss? Oder “war” dieser Code nur zum Probieren?
Wenn ich deinen (3.) Code in die functions.php und den 4. Code in die Sidebar packe, bekomme ich keine Ausgabe. Was mach ich falsch?
Um die Sache noch etwas zu verkomplizieren; wäre es nicht günstiger, über Deine Methode gleich das Page-widget zu hacken?
@mike: Codeblock 2 ist nur zum testen der Ausgabe. Code 3 in die functions.php und Code 4 oder 5 in die Sidebar.
Du machst nichts falsch. Du hast nur bevor der Code der Sidebar ausgeführt wird, eine andere Post global. Damit stimmt die eigentlich erwartete Post ID nicht mehr und es kommt zu keiner Ausgabe. Ich hatte das hier auch einmal.
Du kannst mich gerne anrufen (Impressum).
Lieber Micha,
bisher hatte ich für jede “statische” Hauptseite mit ihren Unterseiten eine eigene Sidebar eingebunden.
Deine Lösung ist deutlich eleganter. Ich werde sie mal mit der Testinstallation ausprobieren. Wenn es klappt, ersetzt sie meine bisherige Krückenlösung.
Vielen Dank für diese komfortablere Lösung.
Ein frohes Neues Jahr wünschend
Dieter
Danke Dieter und ebenfalls ein gesundes Neues Jahr!
Eventuell mußt du Das Markup ändern, je nachdem, wie deine Sidebar aufgebaut ist. Aber das sollte für dich kein Problem darstellen.
Ohweh, das hab ich schon ewig gesucht, bisher hab ich die Kinder immer per CSS ausgeblendet (Äusserst umständlich bei starker Verschachtelung…). Vielen Dank, und schönes Neues!
Danke mike.
Dir auch ein gesundes Neues Jahr!
Micha,
Du traust mir mehr zu als ich mir selbst.
Gruß
Dieter
Vielen Dank für den Hinweis mit get_post_ancestors.
Hast Du noch einen Tipp, für folgendes Problem? Um in Deinem Beispiel zu bleiben, möchte ich bei einem Click auf CMS, soll ab CMS der gesamte Subbaum angezeigt werden, aber ohne “Eltern” oder “SChwestern” von CMS.
Eine Beschreibung meiner Frage findest auch im Wordpress-Forum
Da Dirnbocher: Wenn ich dich richtig verstanden habe, mußt du meine Funktion verwenden, aber ohne array_reverse. Dann ist
$page_ancestors[0]die nächst übergeordnete Seite. Probiers mal.function wpe_highest_ancestor(){
global $post;
$page_ancestors = get_post_ancestors($post->ID);
if(!empty($page_ancestors[0])){
$child_of = $page_ancestors[0];
}else{
$child_of = $post->ID;
}
return (int) $child_of;
}
Achtung Update. Ich habe den Code optimiert. War mein Fehler, jetzt wird nicht mal mehr die Datenbank beansprucht.
Mensch das hab ich vor kurzem mal gesucht und damals allerdings deinen Beitrag nicht gefunden.
Werd ich mir gleich mal abspeichern.
Dankeschön!
Hi Micha, das klang -für mich – doch etwas einfacher als ich das raff.
Kurzfassung: ich bekomme es nicht hin.
Dein 2. Codeblock; sehe ich das richtig, dass der a: in die sidebar muss, und b: dass ich die ids alle manuell anfassen muss? Oder “war” dieser Code nur zum Probieren?
Wenn ich deinen (3.) Code in die functions.php und den 4. Code in die Sidebar packe, bekomme ich keine Ausgabe. Was mach ich falsch?
Um die Sache noch etwas zu verkomplizieren; wäre es nicht günstiger, über Deine Methode gleich das Page-widget zu hacken?
@mike: Codeblock 2 ist nur zum testen der Ausgabe. Code 3 in die functions.php und Code 4 oder 5 in die Sidebar.
Du machst nichts falsch. Du hast nur bevor der Code der Sidebar ausgeführt wird, eine andere Post global. Damit stimmt die eigentlich erwartete Post ID nicht mehr und es kommt zu keiner Ausgabe. Ich hatte das hier auch einmal.
Du kannst mich gerne anrufen (Impressum).