How to display only top level posts in loop via WP_Query?

This solution is based on some code by Justin Tadlock. pre_get_posts is called before WordPress gets the posts of the main loop. Basically, you test to see if the page is the archive of the post type and make sure post_parent hasn’t been set. Then you set post_parent to 0, which is the default parent of top level posts. Easy as pie.

 <?php
    //pre_get_posts filter is called before WordPress gets posts
    add_filter( 'pre_get_posts', 'my_get_posts' );
    
    function my_get_posts( $query ) {
        //If the user is viewing the frontend, the page is an archive and post_parent is not set and post_type is the post type in question
        if ( ! is_admin() && is_archive() && false == $query->query_vars['post_parent'] &&  $query->query_vars['post_type'] === 'my_post_type')
            //set post_parent to 0, which is the default post_parent for top level posts
            $query->set( 'post_parent', 0 );
        return $query;
    }
    ?>

Leave a Comment