1

This is the code from the codex most commonly used for sidebar menus. It displays the child pages of the top level ancestor and the ancestor itself.

There is one thing about this code I would like to change - I don't want the top level ancestor displayed if it has no children! It doesn't make much sense to have a one link menu which points to itself.

How can I edit this code to achieve this? I've previously asked a similar question, but was never given the correct answer. All the answers given also listed children of the parent's child (the second level child page).

In functions.php

// Sub-pages menu
if(!function_exists('get_post_top_ancestor_id')){
/**
 * Gets the id of the topmost ancestor of the current page. Returns the current
 * page's id if there is no parent.
 * 
 * @uses object $post
 * @return int 
 */
function get_post_top_ancestor_id(){
    global $post;

    if($post->post_parent){
        $ancestors = array_reverse(get_post_ancestors($post->ID));
        return $ancestors[0];
    }

    return $post->ID;
}}

Calling it:

<ul class="subpages">
    <?php wp_list_pages( array('title_li'=>'','include'=>get_post_top_ancestor_id()) ); ?>
    <?php wp_list_pages( array('title_li'=>'','depth'=>1,'child_of'=>get_post_top_ancestor_id()) ); ?>
</ul>

This code checks if a page has children, I'm curious if this could be merged with the codes above to create the correct code:

$children = get_pages('child_of='.$post->ID);?>
if( count( $children ) != 0 ) { show list as normal }
else { show "no parent" text }

2 Answers 2

2

Personally, I think this is the neatest, least intensive (database querying) solution:

<?php
$parentid = $post->post_parent ? @ array_pop( get_post_ancestors( $post ) ) : $post->ID;
$children = wp_list_pages(
    array(
        'child_of' => $parentid,
        'title_li' => '',
        'echo'     => false,
    )
);

if ( $children ) : ?>

    <ul class="subpages">
        <li><a href="<?php echo get_permalink( $parentid ) ?>"><?php echo get_the_title( $parentid ) ?></a></li>
        <?php echo $children ?>
    </ul>

<?php else : ?>

    Nothing!

<?php endif ?>
3
  • 1
    What about active class for the parent?
    – Howdy_McGee
    Feb 25, 2014 at 18:15
  • I found this to be a nice solution. Just added 'depth' => 1 and it was good to go. Feb 25, 2014 at 19:00
  • @Howdy_McGee Easily done with if ( is_page( $parentid ) ) echo ' class="current_page_item"'; Feb 26, 2014 at 10:44
0

This may not be exactly what you're looking for but I use a Frankenstein approach, it gets the job done:

First, let's check if we even need to show subpages, this will make sure this page either has children or is a child and we're not on a 404 page - if true, we will get the ancestor (parent) ID, then run WP_List_Pages twice so that we show the parent and children all in the same list.

<?php if((hasChildren($post->ID) || $post->post_parent) && !is_404()) : $ancestorID = getAncestorID(); ?>
<ul class="subpages">
    <?php wp_list_pages(array('title_li' => '', 'include' => $parentID, 'echo' => 1)); ?>
    <?php wp_list_pages(array('title_li' => '', 'child_of' => $parentID, 'echo' => 1)); ?>
</ul>
<?php endif; ?>

Into your functions.php File

/** Function to get Ancestor ID **/
function getAncestorID(){
    global $post;
    $id = $post->ID;

    if ($post->post_parent){
        $ancestors=get_post_ancestors($post->ID);
        $root=count($ancestors)-1;
        $id = $ancestors[$root];
    } 
    else if(is_singular('post') || is_archive() || (is_home() && !is_front_page())){
        $id = get_option('page_for_posts');
    }

    return $id;
}

/** Check if page Has Children **/
function hasChildren($pid) {
    $children = get_pages('child_of='.$pid);
    if($children)
        return true;
    else
        return false;
}
1
  • Thanks, I'm going to leave this question open for a while longer... see if there is a less clunky approach. Feb 25, 2014 at 16:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.