filter default query to show just selected level of child pages in wordpress

WordPress Development Asked by Hafiz Shehroz on January 4, 2022

I’m working on a site that has a fairly large page structure a few levels deep – in some sections there are a lot of pages.

So I want to have functionality if user choose on select box level 1 then only pages in level 1 will show in below list of pages.
if he choose level 2 then only level 2 pages, same go to level 3 level 4 level 5 level 6.

it’s working for top level parent pages when I set query_vars[‘post_parent’] = 0; and I want to have same functionality to show list of level 1 child page,level 2 child pages and so on…

I am stuck on it. please I will be great full if anyone can help me for it. Thanks
see screenshot link

function level_page_admin_posts_filter( $query ) {
  global $pagenow;
  if ( is_admin() && $pagenow == 'edit.php' && !empty($_GET['lavel_pages'])) {
      $level = $_GET['lavel_pages'];
      if($level == 'parent'){
        $query->query_vars['post_parent'] = 0;
      if($level == 1){
      if($level == 2){

add_filter( 'parse_query', 'level_page_admin_posts_filter' );

function admin_page_filter_level_pages() {
  global $wpdb;
  if (isset($_GET['post_type']) && $_GET['post_type'] == 'page') {
  $sql = "SELECT ID, post_title FROM ".$wpdb->posts." WHERE post_type = 'page' AND post_parent = 0 AND post_status = 'publish' ORDER BY post_title";
  $parent_pages = $wpdb->get_results($sql, OBJECT_K);
  $select = '
    <select name="lavel_pages">
      <option value="parent">Parent Pages</option>
      <option value="1">Level 1</option>
      <option value="2">Level 2</option>
      <option value="3">Level 3</option>
      <option value="4">Level 4</option>
  $select .= ' </select>';
  echo $select;
} else {
add_action( 'restrict_manage_posts', 'admin_page_filter_level_pages' );

One Answer

So it looks like get_ancestors() is the function you need to be able to figure out what 'level' something is. The number of results returned from get_ancestors corresponds to your 'level' number, with 0 results meaning parent page.

And so the problem you have is that this number isn't available as a query argument. Therefore, perhaps the simplest option would be to store this as a meta field against all your pages when they're saved. You could achieve this with a simple hook, like:

add_action('save_post', 'hafiz_update_level_number', 10, 2);
function hafiz_update_level_number($postID, $post) {
   if ($post->type == 'page') {
        update_post_meta($postID, 'hafiz_level_number', get_ancestors($postID)) ;

Now don't need to have the if ($level == ?) code, you just make sure you have a number where 0 is 'parent' and 1 is level 1, 2 is level 2, etc. and you can make your query work something like this:

$query->query_vars['meta_key'] = 'hafiz_level_number';
$query->query_vars['meta_value'] = $levelNumber;

You may have to edit this for how you're using this $query object, but hopefully you get the general idea here.

Note you have the obvious problem that this new value is not set unless a post has been saved or updated after you install this hook, so you will need to either manually open and save every page, or write a quick script to run once which loops through every page and sets this value for every page.

Hope that's helpful. This code is untested but the intention is to outline a way you can write the complete code you need to answer your question. Please respond with any questions

Answered by mozboz on January 4, 2022

Add your own answers!

Ask a Question

Get help from others!

© 2024 All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP