Do Not Display Parent Page if No Subpages

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.

Read More

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 }

Related posts

2 comments

  1. 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 ?>
    
  2. 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;
    }
    

Comments are closed.