Hey there I am trying to fetch all direct children of a page. But I am getting only the parent two pages. Any ideas?


function childpages_func( ){
    $args = array(
        'child_of' => $post->ID,
        'parent' => $post->ID,
        'hierarchical' => 0,
        'sort_column' => 'post_date',
        'sort_order' => 'menu_order'
    $childpages = get_pages( $args );
        foreach($childpages as $child){
            $ret.= '<a href="'.get_page_link($child->ID).'" title="'.$child->post_title.'">
                        <img src="'.wp_get_attachment_url(get_post_thumbnail_id($child->ID)).'" title="'.$child->post_title.'">
    return $ret;

My pagestructure looks like this:


Parent 2

  • Child 1 >This should display its children (Code is embedded here)

    -- Child 1a

    -- Child 2a

    -- Child 3a

  • Child 2

Parent 3

I want to display only the direct children of "Child 1" (Child 1a, 1b and 1c...)

But my code returns:

  1. Parent

  2. Parent 2

that's it.

Thank you!


The problem here is twofold.

Firstly, you're using 'parent' => $post->ID,. $post is a global variable, not a super global, so you have to state that you intend to use it before doing so with:

global $post;

But, as always, it's easier to use the APIs than to go for the raw data, and you would be better off with:

'parent' => get_the_ID(),

Or even better, if we apply good coding practices, we get:

function display_child_pages( $post_id=0 ){
    'parent' => $post_id,

<?php display_child_pages( get_the_ID() ); ?>

Now the function declares clearly what it does, and can output the child pages of any page, not just the one we're currently on. The function is also now significantly easier to write tests for thanks to the post_id argument.

Note that the above function should echo, not return the HTML, otherwise you end up encouraging early escaping and all the security issues that come with it.

Secondly, your query is doing exactly what you asked it to, but it's more explicit than what you had in mind.

The query asks for all posts with the parent X, which in this case was 0 due to the error above. Child posts do not have that parent though, they have a different parent!

To get around this problem, you will need to recurse down the tree, running a query for each link to find its children, and a query for each child to find the grandchildren. parent only looks at the parent, it doesn't go down multiple generations.

For example, "Parent 2" is not the parent of "Child 1a". "Child 1" is the parent of "Child 1a". This is why it wasn't picked up by the query.

Additional Notes

  • Don't use get_pages, use WP_Query instead and cut out the middle man, it'll be a little faster, and all the parameters are the same
  • What happens if there are no children? There's no check if get_pages actually found any pages
  • You use get_post_thumbnail_id but you never check if the page has a featured image, if there is no featured image it will be impossible to click the link or even see it!
  • What is this 'child_of' => $post->ID,? There is no child_of parameter, this looks like guesswork. Why guess when there's a full list of all the supported options on the Codex under WP_Query?
  • Hey there, thank you for the nice and informative explanation. It works like a charm. But one thing I need to address: There is a 'child_of' parameter:
    – GrampaRay
    Oct 17 '16 at 18:40
  • Check here: codex.wordpress.org/Function_Reference/get_pages
    – GrampaRay
    Oct 17 '16 at 18:40
  • ah, judging from that, you would need to remove the parent parameter, so it pulls in all pages, then add child_of, resulting in a query that doesn't scale and gets more expensive and slower as you add more pages. That's wasteful and I wouldn't recommend it
    – Tom J Nowell
    Oct 17 '16 at 19:02
  • Good to know. Thank you! I will recreate my code to make it faster and more scaleable
    – GrampaRay
    Oct 17 '16 at 19:21

Your Answer

