Get Ancestor featured image

Given this hierarchy:

  • Page 1
    • Page 2
      • Page 3
        • Page 4

This line, where $post represents Page 4:

$parents = get_post_ancestors( $post->ID );

Will return 3 IDs, for these pages, in this order:

  1. Page 3
  2. Page 2
  3. Page 1

So this line:

$id = ($parents) ? $parents[count($parents)-1]: $post->ID;

Is the equivalent of:

$id = ($parents) ? $parents[2]: $post->ID;

Which means that it will only check whether page 1 has a post thumbnail. It will ignore pages 2 & 3. Because array indexes start at 0, count($parents)-1 means that $id will always be the last item in the list, which will be the top-level page.

What you want to do is loop through $parents, from immediate parent, to grandparent, to great grandparent, until a thumbnail is found. Then break the loop and return the thumbnail:

$thumbnail=""; // We will replace this if/when we find a thumbnail.
$parents   = get_post_ancestors( null ); // null will get the current post.

foreach ( $parents as $post_id ) { // Loop through parent pages.
    if ( has_post_thumbnail( $post_id ) ) { // Check if this ancestor has a thumbnail.
        $thumbnail = get_the_post_thumbnail( $id, 'thumbnail' ); // If it does, get it...
        break; // ...then stop looping.
    }
}

echo $thumbnail;

The problem with this code is that if the current page has a thumbnail, it won’t get displayed, because we’re only looping through parents. The simplest way to get around this is to add the current page ID to the list of IDs we’re looping through:

$thumbnail=""; // We will replace this if/when we find a thumbnail.
$parents   = get_post_ancestors( null ); // null will get the current post.

array_unshift( $parents, get_the_ID() ); // Add the current page to the list of pages we're checking.

foreach ( $parents as $post_id ) { // Loop through parent pages.
    if ( has_post_thumbnail( $post_id ) ) { // Check if this ancestor has a thumbnail.
        $thumbnail = get_the_post_thumbnail( $id, 'thumbnail' ); // If it does, get it...
        break; // ...then stop looping.
    }
}

echo $thumbnail;