Given this hierarchy:
This line, where $post
represents Page 4:
$parents = get_post_ancestors( $post->ID );
Will return 3 IDs, for these pages, in this order:
- Page 3
- Page 2
- 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;