For a Web project I am working on I wanted to use WordPress as a CMS for flat pages only. No blog posts, no categories, simply a hierarchical page tree (too complicated for the user). Thus I installed the CMS Tree Page View plugin, set some permissions and tried to render a hierarchical menu in the navigation bar of the Web site.
Well, I tried. It is not as simple as it seems to render a hierarchical menu in WordPress that does the following:
- always display all top level (root) pages
- always display the current path down to the current page
- always display all child pages of the current page
- always display siblings of the current page
This is pretty much the behavior I’d expect from a hierarchical menu in a CMS.
Unfortunately it seems this is not very easy to implement in WordPress. The wp_list_pages function with all its options does not allow to render a page tree that goes up to the top level. And none of the samples on the page is the right solution (on a side note: the advanced samples on the page are not targeting the latest WordPress releases and won’t work out of the box as they target the wrong database tables) – they render the current parent page or siblings or… something.
Anyhow, here is a short snippet that provides a hierarchical page menu in WordPress, simply add this to the template where ever you would otherwise just have the call to wp_list_pages:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?php global $blog_id; // anchestor pages $relations = get_post_ancestors($post->ID); // select child pages, siblings and top level pages $result = $wpdb->get_results( "SELECT ID FROM wp_{$blog_id}_posts WHERE ( " . "post_parent = $post->ID OR ". // child pages "post_parent = $post->post_parent OR ". // siblings "post_parent = 0 ) ". // top level pages "AND post_type='page'" ); if ($result) { foreach($result as $pageID){ array_push($relations, $pageID->ID); } } // move the chain up until we are at the root $parent = $post->post_parent; while($parent) { array_push($relations, $parent); $result = $wpdb->get_results( "SELECT ID, post_parent FROM ". "wp_{$blog_id}_posts WHERE id = $parent AND post_type='page'" ); if($result && $result[0]->ID) { $parent = $result[0]->post_parent; } else { $parent = 0; // quit the loop } } // build a relations string... $relations_string = implode(",",$relations); // ... and list all pages wp_list_pages('title_li=&depth=0&sort_column=menu_order&&include='. $relations_string); ?> |
I hope this helps someone who runs into the same issue… and – if there is a better, simpler solution that I did not see or find, please leave a comment!
2 comments
Really? · 21.05.2012 at 12:47
What if I don’t use WPMU?
What if I don’t use default DB prefix?
If you want us to improve this snippet’ functionality, please place it to github or bitbucket or whatever VCS
Admin comment by Michael · 15.06.2012 at 14:17
Hi! Please feel free to take the snippet and put it on Github or any other location and improve it, fine for me…