Something is changing your results from get_ancestors()
or something is changing your query which “changes” your child pages to grandchild pages when queried on the page. It also seems from comments that the post ID’s does not stay constant on the page.
What immediately catches my eye from your updated code is that your custom query is not resetted after you are done. You have to remember, the_post()
sets the $post
global to the current post being looped over in the loop, and once the loop is done, $post
will hold the last post object of the loop.
You can add var_dump( $post );
before and after your current code and you will see that the value of $post
differs. That is why you must always reset custom queries after you are done. Simply add wp_reset_postdata();
directly after endwhile
just before endif
. Doing a var_dump( $post );
now before and after the loop should render the same value.
$post
is a global variable that is changed by many things, and bad code (like the code in your question) can change the $post
global, which in turn returns wrong info, which in turn have you on a wild goose chase to find out why. A more reliable method is to use get_queried_object()
to return the current page object. For an explanation, please feel free to check my question and the answer accepted answer from @gmazzap. Note, however this being reliable, query_posts
breaks the main query object which holds the queried object.
I also note that you hardcode ID’s, do not do that. Every post/page have a post_parent
property. If a post type is non-hierarchical, like posts, the post_parent
value will always be 0
because non-hierarchical post types don’t have any hierarchy. Hierarchical post types like pages will either have 0
as post_parent
if it is a top level page or have a numeric value if it is child/grandchild page, the value in post_parent
will represent the ID of the page’s direct parent.
-
To correctly get the page id of a page being viewed, use
get_queried_object()->ID
orget_queried_object_id()
instead of$post->ID
. -
To get the immediate post parent ID of the current page being viewed, use
get_queried_object()->post_parent
-
To get the top level parent, use
end( get_ancestors( get_queried_object()->ID, 'page' ) )
. Remember, the top level parent will be the last ID in the array of ID’s returned byget_ancestors
, the first ID will be the direct parent.
To rewrite your code, use something like this to get direct children of the page being viewed:
$page_object = get_queried_object();
// Check if page is top level or not and set $args accordingly
if ( $page_object->post_parent == 0 ) { // Top level page
$parent_ID = (int) $page_object->ID;
} else { // Page is a child/grandchild page
$parent_ID = (int) $page_object->post_parent;
}
// Setup query args
$args = [
'post_parent' => $parent_ID,
'post_type' => 'page'
];
$q = new WP_Query( $args );
if ( $q->have_posts() ) {
while ( $q->have_posts() ) {
$q->the_post();
// Run your code to display posts
}
wp_reset_postdata(); // EXTEMELY IMPORTANT!!!!!!!
}
To conclude, to determine the current hierarchy of a page, do the following
$current_page = get_queried_object();
if ( $current_page->post_parent == 0 ) {
echo 'This is a parent';
} else {
$hierarchy = get_ancestors( $current_page->ID, 'page' );
$count = count( $hierarchy );
$child = ( $count == 1 ) ? 'child' : 'grandchild';
echo 'This is a ' . $child . ' page';
}