# Subnav menu - adapt to show the same on parent, child & grandchildren pages?

I found this very useful code at the wp codex, it basically lists out the parent, child and grandchild pages, I'm using it in my sidebar and it works well for the parent and children pages, but when you go to a grandchild page, the menu changes and it now only shows the child/grandchild, instead of the same menu on the parent & child pages. how can i make it show the same on all the pages?

Also i'd like the parent title to be an actual link rather than just text and I can't seem to figure that out. help is greatly appreciated!!

            <?php
if($post->post_parent) {$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0");$titlenamer = get_the_title($post->post_parent) ; } else {$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");$titlenamer = get_the_title($post->ID); } if ($children) { ?>

<h2> <?php echo $titlenamer; ?> </h2> <ul> <?php echo$children; ?>
</ul>
<?php } ?>

-

https://gist.github.com/3853924

This is a plugin I created and usually use for this type of functionality. The key is the little function down at the bottom of the file that searches for the top-level ancestor. There's also part of the code that will print out categories instead of pages when you're on a blog or search page; you can turn it off by commenting out line 43.

It will display as many levels of page hierarchy as you care to make, and it will always display the top-level parent page levels.

You can install it by downloading the file, adding it to your plugins folder, and activating. If you want to use it in your code rather than a widget area, you can do something like this:

$nav = new DTW_Navigation_Widget;$nav->widget();


The pertinent part of the widget is this:

// Somewhere in your functions file
/** Find the top-level parent of this post */
function my_get_ancestor_id($post) { if ($post->post_parent ) {
$ancestors = get_post_ancestors($post->ID);
$root = count($ancestors)-1;
$parent = get_post($ancestors[$root]); } else {$parent = $post; } return$parent->ID;
}


and this:

// Also in your functions file
/** Find the top-level parent of this post */
function related_pages() {
// Where are we?
global $post;$parent_id = my_get_ancestor_id($post);$title = get_the_title($parent_id);$link =  get_permalink($parent_id);$title = "<a href='$link' title='$title'>$title</a>"; if ( !empty($parent_id)  ) {
$args = array( 'title_li' => '', 'child_of' =>$parent_id,
'echo' => 0,
);
$nav = wp_list_pages($args);
}
// Let's hide this if there aren't any sub-pages or sibling pages... it tends to break.
if ( !empty($nav) ) { echo "<ul id=\"sidebar-subnav\">" .$nav  . "</ul>";
}
}


Then wherever you want to get a list of sub-pages/sibling pages: <?php related_pages(); ?>

-
thanks but i'd rather not use a plugin for this, i would like to learn the functionality and put it right in the code. thank you though. –  jamie Oct 10 '12 at 21:12
No problem. That plugin has the solution in it, if you care to deconstruct it and just use the parts you need. I'll post a more complete answer with just those parts. –  guiniveretoo Oct 12 '12 at 2:35
cool I'll take a look at it, because I'm still looking for a solution :) –  jamie Oct 17 '12 at 18:20

The reason behavior changes is because that code only checks for immediate parent. So it doesn't go looking for parent of a child.

To go through whole hierarchy you would need to retrieve and process it with get_post_ancestors().

-
can you explain a little further how i would alter this existing code to use get_post_ancestors() please? –  jamie Oct 10 '12 at 21:12

I finally figured this out. I didn't want it to show up at all on pages without children, so the first if statement checks and only displays the menu if the parent has children. This menu stays the same whether you are on the parent, child, or grandchild page. :)

<?php if (  has_children() ) { //makes menu title only show up on pages with descendents ?>

<?php if ( 0 == $post->post_parent ) { //sets parent page title ?> <li> <div class="widget"> <h2><?php the_title(); ?></h2> <?php } else { //puts topmost parent page title$parents = get_post_ancestors( $post->ID ); echo ' <li> <div class="widget"> <h2>' . apply_filters( "the_title", get_the_title( end ($parents ) ) ) . '</h2>';

}?>

<?php } ?>

<?php //shows children & grandchildren of page no matter what level you're on
if(!$post->post_parent){ // will display the subpages of this top level page$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0"); } else { if($post->ancestors) {

$ancestors = end($post->ancestors);
$children = wp_list_pages("title_li=&child_of=".$ancestors."&echo=0");
}
}

if ($children) { ?> <ul> <?php echo$children; ?>
</ul>
<?php echo '</div></li>'; } ?>

-