admin管理员组文章数量:1331849
I have a post category structure like this:
- news
- news / conferences
- news / newsletter
In Appearance > Menu, I have added 3 menu items.
One each for the categories News, Conferences, Newsletter.
However, the News page also displays posts from Conferences and Newsletter.
How do I exclude posts from subcategories from being displayed in the parent category's page?
Thanks
I have a post category structure like this:
- news
- news / conferences
- news / newsletter
In Appearance > Menu, I have added 3 menu items.
One each for the categories News, Conferences, Newsletter.
However, the News page also displays posts from Conferences and Newsletter.
How do I exclude posts from subcategories from being displayed in the parent category's page?
Thanks
Share Improve this question asked Mar 2, 2014 at 9:51 SteveSteve 1,75719 gold badges66 silver badges115 bronze badges 1- I'm so curious about this. It even seems to be the behaviour I'm experiencing in the backend admin. See: "Why does admin post list for a term also show posts for all child terms?" wordpress.stackexchange/questions/318175/… Is this really standard behaviour? – Robert Andrews Commented Nov 1, 2018 at 12:11
6 Answers
Reset to default 3I rewrote the code from a post at WP Engineer:
function wpse_filter_child_cats( $query ) {
if ( $query->is_category ) {
$queried_object = get_queried_object();
$child_cats = (array) get_term_children( $queried_object->term_id, 'category' );
if ( ! $query->is_admin )
//exclude the posts in child categories
$query->set( 'category__not_in', array_merge( $child_cats ) );
}
return $query;
}
add_filter( 'pre_get_posts', 'wpse_filter_child_cats' );
Give it a try by pasting the snippet in your functions.php
. Please keep in mind that a post can't belong to both parent category and child category, or you won't get it displayed.
Use category__in
instead of cat
in your query.
As you know already, cat
will query a category and it's sub categories:
$category = get_category (get_query_var('cat'));
WP_Query( 'cat'=>$category, 'post_type' => 'post' );
However, when using category__in
, you'll will not get results from the subcategory.
$category = get_category (get_query_var('cat'));
WP_Query( 'category__in'=>$category, 'post_type' => 'post' );
The documentation on querying based on categories is here.
If you want to include any and all posts that have the category that is currently being queried, you can use the following. This could potentially include posts that have sub/child categories of the queried category, but only if they also have the parent category. It will not include posts that only have a child category. In other words, given the following:
Category 1
Category 2, which is a child category of category 2
Post A, which has category 1 only
Post B, which has category 2 only
Post C, which has both category 1 and category 2
this query will return posts A and C, but not B
function cat_query_filter($query) {
if (!is_admin() && $query->is_main_query() && is_category()) {
$queried_cat_obj = get_queried_object();
$queried_cat_id = $queried_cat_obj->term_id;
$query->set('category__in', $queried_cat_id);
}
}
add_action('pre_get_posts', 'cat_query_filter');
The answer provided by @createscape is a good one, but would exclude posts like post B, which may or may not be what you want. So, depending on what you want to be included in your list of results, you could either use that solution or this one. Additional info here: https://developer.wordpress/reference/classes/wp_query/#category-parameters
That works well and prevents posts in child categories from showing up in the parent category listing. However, make sure and have a post in that parent category, or you'll get a not found error if someone clicks on the parent category menu item.
I wrote my own function in order to exclude subcategory posts from the loop, as I found the code above didn't work for me.
In my theme archive.php file, above the loop, I list the subcategories:
<?php
$current_cat = get_queried_object();
$args = array( 'parent'=>$current_cat->term_id, 'child_of' => $current_cat->term_id, );
$categories = get_categories( $args );
foreach($categories as $category) { ?>
<h2><?php echo $category->name ;?></h2>
<p> etc....</p>
<?php } ?>
In my functions.php file, I've added the following custom function using pre_get_posts:
add_action( 'pre_get_posts', 'main_query_without_subcategory_posts' );
function main_query_without_subcategory_posts( $query ) {
if ( ! is_admin() && $query->is_main_query() ) {
// Not a query for an admin page.
// It's the main query for a front end page of your site.
if ( is_category() ) {
//Get the current category
$current_category = get_queried_object();
//get the id of the current category
$current_cat_id = $current_category->term_id;
//find the children of current category
$cat_args = array( 'parent'=>$current_category->term_id, 'child_of' => $current_category->term_id, );
$subcategories = get_categories( $cat_args );
//Get a list of subcategory ids, stick a minus sign in front
$subcat_id = array();
foreach($subcategories as $subcategory) {
$subcat_id[] = " -". $subcategory->term_id;
}
//join them together as a string with a comma seperator
$excludesubcatlist = join(',', $subcat_id);
//If you have multiple parameters, use $query->set multiple times
$query->set( 'posts_per_page', '10' );
$query->set( 'cat', ''.$current_cat_id.','.$excludesubcatlist.'' );
}
}
}
Then in the archive.php, below the subcategories, I've added the regular WordPress loop which is now being modified by the above function:
<?php while (have_posts() ) : the_post(); ?>
<h2><?php the_title();?></h2>
<p> etc....</p>
<?php endwhile;?>
Though the WordPress codex says that using "category__in" will exclude posts from subcategories, that didn't work for me and subcategory posts were still showing.
https://codex.wordpress/Class_Reference/WP_Query#Category_Parameters
https://developer.wordpress/reference/hooks/pre_get_posts/
Okay, as of 2019 I had to use slightly modified code and it works with any taxonomy. Not only with standard category. I used it with my setup of woocommerce and wp, preventing products from nested categories being displayed in parent cat:
add_action('parse_tax_query', 'wpse_filter_child_cats');
function wpse_filter_child_cats( $query ) {
if ( is_tax( 'product_cat' ) ) {
$queried_object = get_queried_object();
$child_cats = (array) get_term_children( $queried_object->term_id, 'product_cat' );
if ( ! $query->is_admin ) //exclude the posts in child categories
{
$query->tax_query->queries[] = [
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => array_merge( $child_cats ),
'operator' => 'NOT IN'
];
}
}
}
本文标签: categoriesExclude sub category posts from category display
版权声明:本文标题:categories - Exclude sub category posts from category display 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742217898a2434900.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论