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.