3

By default WordPress will list posts on each category in its hierarchy.

Example:

Parent

/- child

/-- grandchild

When viewing the "Parent" category you will see a list of posts from child, grandchild and parent - even if the post is just ticked in "Grandchild".

My question is: How do I only show posts when viewing the last child? Is there a built in WordPress function for this?

e.g.:

[grandchild categories] = array of grandchildren

if(in_array( [grandchild categories] )) : show posts

else:

do nothing
7
  • You have to clarify, because this way the counter question is: when viewing what, where and how exactly? Oct 6, 2014 at 10:58
  • Besides, generally this is wanted behavior in hierarchical taxonomies, if you have »parent: animal > child: mammal > grandchild: dog« and you selected »dog«, then you can be sure that a dog is also a animal and a mammal. Oct 6, 2014 at 11:11
  • 1
    @ialocin I think I understand the OP. On a category page, posts is shown from the specific category, it's child categories and the parent category by default (BTW, why Wordpress does this is above me, does not make sense, what is the use of these parent/child relationships then if they are combined on a category page). Now, the question is, how do you display posts from the specific category only (if you visit cat 1, only cat 1 posts should display), thus excluding its parent and any children categories' posts it might have Oct 6, 2014 at 11:17
  • I get your point, but I still think it's generally logical to show children in hierarchical taxonomies. @PieterGoosen Oct 6, 2014 at 11:34
  • 1
    What the desirable behavior for taxonomy archives is up for debate I think, or at least it depends on the use case - like @PieterGoosen said before. And it is not equal to the question how to handle the SEO/duplicate content matter. For the latter you should probably work with meta tags like this <meta name="robots" content="noindex,follow"/>, pretty much regardless how you organize your archives. Oct 6, 2014 at 13:33

3 Answers 3

2

There is of course the include_children parameter for WP_Query as part of the taxonomy parameters. Which I suppose should work like this for you:

$args = array(
    'tax_query' => array(
        array(
            'include_children' => false
        ),
    ),
);
$query = new WP_Query( $args );

Or via parse_tax_query for your category archive:

add_filter( 
    'parse_tax_query', 
    'wpse163572_do_not_include_children_in_category_archive_parse_tax_query' 
);
function wpse163572_do_not_include_children_in_category_archive_parse_tax_query( $query ) {
    if ( 
        ! is_admin() 
        && $query->is_main_query()
        && $query->is_category()
    ) {
        // as seen here: http://wordpress.stackexchange.com/a/140952/22534
        $query->tax_query->queries[0]['include_children'] = 0;
    }
}

Note: Thanks to @PieterGoosen this is now tested and confirmed working.

3
  • 1
    Tried and tested, your second approach is perfect, and I think the more correct way to do it. I'm not fond of replacing the main query with a custom one. +1. Oct 6, 2014 at 14:41
  • Personally I almost never use secondary, custom queries, but I almost always include them in my answers here, just because it can be useful to others and it demonstrates what we are altering via the hooks. @PieterGoosen Oct 6, 2014 at 14:53
  • Totally agreed. Oct 6, 2014 at 15:01
1

Those of us who have developed static websites with pages will understand the problem as Pieter has outlined in the comments above.

Essentially if one could create a page and list content on that page one has the desired effect but it is useful to use the category system in wp to manage content and order it.

Here is what I've done and have working:

I wrote a small function around "get_term_children" - a wordpress function.

function category_has_children( $term_id ){ 
    $children = get_term_children( $term_id, "category" );
    if(is_array($children)){
      return $children;
    } else {
      return false;
    }
}

Then on my category page before the loop I check if the "category_has_children":

<?php if( category_has_children( $cat ) == false) : ?>

show posts as this is the last child category.

<? endif; ?>
0

This is a more optimized method to hide posts except for the last category:

add_action( 'pre_get_posts', 'roka_hide_posts_if_category_has_child' );
function roka_hide_posts_if_category_has_child( $query ) {

    if ( ! is_admin() && $query->is_main_query() && is_category() ) {
        $term = get_queried_object();

        $children = get_terms( $term->taxonomy, array(
            'parent'    => $term->term_id,
            'hide_empty' => false
        ) );
        
        if( $children ) {
            $query->set( 'page_id', -1 );
        }
    }

}

This code sets the page_id to -1 and creates an empty result indexed query that returns quickly.

You will also need some more codes to display clickable sub-categories in such categories.

Your Answer

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

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