WordPress – list multi-level parent pages when on a 3rd level child page

I’m working on a website at the moment, and the navigation works as follows (by client specification).

Underneath the header there is a horizontal navigation listing the top level pages, clicking on one of these takes you to page.php, which has a vertical navigation in the sidebar listing the sub-pages of that particular page like this:

Read More

2nd level
– 3rd level
– 3rd level
– 3rd level
2nd level
– 3rd level
– 3rd level
– 3rd level

and so on, and so on.

This is the code I am currently using in the vertical navigation:

$children = wp_list_pages('title_li=&child_of='.$post->ID.'&echo=0');
if ($children)
{
    <ul>
        echo $children;
    </ul>
}

What I would like to be able to do is continue to have the same vertical navigation, regardless of the current page level. I’m finding it hard to list the sub-pages of a 1st level page when you’re on a 3rd level page.

Any suggestions greatly appreciated.

Related posts

Leave a Reply

3 comments

  1. Try using get_post_ancestors. This approach seemed to work for me in a similar situation:

    <?php
    global $wp_query;
    $post = $wp_query->post;
    $ancestors = get_post_ancestors($post);
    if( empty($post->post_parent) ) {
        $parent = $post->ID;
    } else {
        $parent = end($ancestors);
    } 
    if(wp_list_pages("title_li=&child_of=$parent&echo=0" )) { ?>
    
    <ul id="secondary-nav">
        <?php wp_list_pages("title_li=&child_of=$parent&depth=1" ); ?>
    </ul><!-- #secondary-nav -->
    
    <?php } ?>
    

    Then I used this to target the current nav states with CSS:

    #secondary-nav li a:hover,
    #secondary-nav li.current_page_item a,
    #secondary-nav li.current_page_ancestor a {
        background:#fcb701;
    }
    

    You’ll probably need to remove the depth parameters to show you’re 3rd level pages.

    I hope this helps!

  2. I think this can be of your help. I had same issue. I had to show up parent page’s layout stuffs (everything) in child page.

    add_action('wp_head', 'init_stuffs');
    function init_stuffs(){
      if( is_page() ){
        $parents = get_ancestors(get_the_id(), 'page');
        if( count( (array) $parents ) >= 2 ){
          //now you can use $parents[1] as parent
          registry()->setParentPageId($parents[1]);
        }
      }
    }
    

    In my case I had to load blurbs of parents. I used WordPress Registry plugin to store $parents[1] id. Then I fetched the blurbs of parents by simply passing parent page id in the function where blurbs data are fetched.

    function fetchBlurbs($parentId = null){
      if(is_null($parentId)){
        //fetch blurb for the page
      }else{
        //fetch blurb of parent page
      }
    }
    
  3. Once you’re inside The Loop, it’s very easy to pull up a reverse history of all page ancestors.

    <?php
        // It's not necessary to globalize $post if you're doing this inside your page.php
        // but if you're in, say, sidebar.php, then you need to declare the global variable
        global $post;
    
        // We have to reverse the array so the top link is the topmost ancestor
        $history = array_reverse( array_map( 'get_post', get_post_ancestors( $post ) ) );
    
        // And if you want to add this page to the list as well, push it onto the end
        $history[] = $post;
    ?>
    
    <ol>
    <?php
        // Now, loop through each page in the list
        foreach( $history as $page ){
             echo "<li><a href='" . get_permalink( $page->ID ) . "' />" . get_the_title( $page ) . '</a>';
        }
    ?>
    </ol>
    

    The key line of course is $history = array_reverse( array_map( 'get_post', get_post_ancestors( $post ) ) ); This does two things:

    1. It maps the IDs returned by get_post_ancestors() to actual WP_Post objects (which, isn’t strictly necessary, since all we really need are IDs to pass to get_permalink() and get_the_title())
    2. It reverses the array order, since get_post_ancestors() puts the immediate parent at the top of the list, and we probably want it at the bottom.