While working on a recent project, I came across a task: exclude certain categories from the archive page. I went the usual way to the WordPress codex -> query_posts and thought the following would do it:
1 2 3 4 5 6 7 8 9 10 | # Exclude categories | archive.php if ( is_home() || is_category('one') || is_category('two') ) { $current_cat = get_query_var( 'cat' ); $exclude_cat = 3; $current_page = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; query_posts("cat=$current_cat,-$exclude_cat&paged=$current_page"); } //The Loop if ( have_posts() ) : while ( have_posts() ) : the_post(); |
This, unfortunately, didn’t work. I then thought of filtering via custom queries. The problem with custom queries is that the filter is applied to each and every query on the page. If you do:
1 2 3 4 5 6 7 8 9 10 | # Exclude categories | functions.php function fd_remove_cat( $nada ) { global $wp_query; if ( is_home() || is_category('one') || is_category('two') ) { $wp_query->query_vars['cat'] = '-3'; } } add_action('pre_get_posts', 'fd_remove_cat' ); |
this will work, but it affects all other queries on the page as well. If you have some custom ‘query_posts’ in your theme, category 3 will be stripped out of all queries on the page.
I came up with this solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # Exclude categories | archive.php if ( is_category('one') || is_category('two') ) { global $wpdb; $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; query_posts( array_merge( array ( 'category__in' => array($cat), 'category__not_in' => array(3,4), 'paged' => $paged ), $wp_query->query ) ); } //The Loop if ( have_posts() ) : while ( have_posts() ) : the_post(); |
The above code preserves the original query and adds/alter defined query variables (also see query_posts, ‘Preserving the Original Query’).
I hope this post keeps you from wasting time while trying to alter the wp_query.