I am trying to set up my wp site where I use posts assigned to categories and subcategories (about 3 levels). I have a list of 1st level categories as my primary menu. When clicked, the intended behavior is to take you to a level 2 subcategory landing page with an Intro post assigned to that subcat and a list of links to the 3rd level sub categories. Upon clicking one of these links, you are taken to the 3rd level category page which displays all of the posts assigned to that 3rd level sub category.

E.g. any_page.php

Primary Menu - Categories: [Cars], Trucks, Trains, Boats


Level 2 - Cars Category Landing Page: Cars Intro Post (assigned to cars cat) followed by List of Title Links of Cars Subcats:[Ford], Toyota, Nissan, Mitsubishi


Level 3 - Ford SubCategory Posts Posts assigned to the FORD subcategory: F250, Mustang, Falcon . . .

I have searched the web for weeks, to see how to achieve this, and cant find anything that really does this with posts (not pages). Some articles sort of touch on this but in those examples the links and posts typically are not isolated to the subcategory in which they are linked and you also get the links and posts assigned to the child and/or parent categories/subcategories too.

I am a bit of a noob at wordpress and PHP so any help would be great!

1 Answer 1


We can change the default behaviour of including posts attached to child categories by mapping the category_name query var (set from pretty permalinks) to category__in (which ignores child categories):

function wpse_184127_ignore_category_children( $wp_query ) {
    if ( $wp_query->is_main_query() && $wp_query->is_category() && $name = $wp_query->get( 'category_name' ) ) {
        if ( $term = get_term_by( 'slug', sanitize_title_for_query( $name ), 'category' ) ) {
            if ( $term->parent )
                $depth = count( get_ancestors( $term->term_id, 'category', 'taxonomy' ) );
                $depth = 0;

            if ( $depth <= 1 ) {
                $wp_query->set( 'category__in', array( $term->term_id ) );
                unset( $wp_query->query_vars['category_name'] );

add_action( 'pre_get_posts', 'wpse_184127_ignore_category_children' );

Update: Added depth checking. Just change $depth <= 1 to whichever expression you need. Currently it will only ignore children for top-level and first-level categories (i.e. depth less than or equal to 1).

  • Thanks @TheDeadMedic Does this code go in functions.php? Commented Apr 14, 2015 at 9:26
  • Yes, functions.php Commented Apr 14, 2015 at 9:30
  • Thanks @TheDeadMedic this works extremely well. Is there any way of slightly modifying this so that it is only true to a certain depth? Commented Apr 14, 2015 at 9:48
  • Of course, check my revision. Commented Apr 14, 2015 at 13:29
  • Thanks so much @TheDeadMedic This works perfectly. You are a life-saver! Commented Apr 14, 2015 at 15:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.