Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

What I am trying to do?

My blog uses a custom taxonomy called edition with terms like us-canada (6), eu (7) and india (8) -- term slug (ID).

I want to make sure that posts not assigned to any specific 'edition' be shown under all the terms (i.e. if a post is not assigned to usa, europe or india, it'll be shown in the archive pages of all these terms).

What I've tried?

Here's the sample code pertaining to one of the terms, which should give you an idea of what I am exactly trying to do, and what I'd be doing wrong.

add_filter('pre_get_posts','better_editions_archive');

function better_editions_archive($query) {

    if ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) {
        $query->set( 'post_type', array( 'post' ) );

        $query->set( 'tax_query',
            array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'category',
                    'field' => 'id',
                    'terms' => array( 1, 2, 4, 5 )
                ),
                array(
                    'taxonomy' => 'edition',
                    'field' => 'id',
                    'terms' => array( 7, 8 ),
                    'operator' => 'NOT IN'
                )
            )
        );
    }

    return $query;
}

What's wrong? The aforementioned code doesn't work (others I've tried: code-1, code-2), it's doesn't change anything. There's no debug error either.

So, what could I be doing wrong?

ALSO, to make sure that the changes also apply to feeds of these terms, I replaced the relevant line in the aforementioned code with this:

function better_editions_archive($query) {

    if ( ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) || ( $query->is_feed() && $query->is_tax( 'edition', 6 ) ) ) {

But that starts to redirect the terms' feeds back to the terms' archives. That is, with the function in place, example.com/edition/usa/feed/ redirects back to example.com/edition/usa/.

Again, I've no clue as to what I'd be doing wrong.

UPDATE: What's worked for me? (But...)

add_filter( 'pre_get_posts', 'better_editions_archive' );

function better_editions_archive( $query ) {
    if ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) {

        $args = array(
            'post_type' => 'post',

            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'category',
                    'field' => 'id',
                    'terms' => array( 1, 2, 4, 5 )
                ),
                array(
                    'taxonomy' => 'edition',
                    'field' => 'id',
                    'terms' => array( 7, 8 ),
                    'operator' => 'NOT IN'
                )
            )
        );

        $query->query_vars = $args;
    }

    return $query;
}

It works, but the problem is, I'd an extended chat discussion with a knowledgeable WordPress developer, and he told me this (you can follow the full conversation here, but it's too lengthy):

And you're then assigning this array as the query_vars. Now the query_vars is a pretty large object. And you're basically overwriting the data in there and just adding your custom ones. This means that you 'unset' everything that is added per default.

He pretty much advised against using this solution, and instead go with the $query->set(); method.

But as you can see far above, I couldn't get the other one to work. So I am here to see if anyone can tell me what I am doing wrong, in a less-technical-speak.

share|improve this question
    
There is a missing ) to close the set method of $query->set( 'tax_query', –  birgire Mar 10 '13 at 17:51
    
@birgire I just noticed your comment as I was about to make an edit. There wasn't any missing ) initially either (the set is actually closed, and the closing ); is in another line further below). Can you please take a good look at the code? –  its_me Mar 10 '13 at 17:56
    
Use the tax_query array on the $query->set method. The developer have right, you overwrite all on query and it is better, if you enhance the query. –  bueltge Mar 12 '13 at 19:08
    
@bueltge Is this what you want me to try? If so, I tried it. It didn't work. If not, can you be a bit more clear? Thanks! –  its_me Mar 12 '13 at 19:43
    
Can you clarify in what way it isn't working? Are you getting no results at all? Or just not the combination of results that you expect? –  vancoder Mar 12 '13 at 20:32
show 6 more comments

2 Answers

up vote 7 down vote accepted
+200

I'll take another shot.

The following should modify the main query, such that it will include in its loop any posts that belong to no term of the Edition custom taxonomy.

add_filter('pre_get_posts','better_editions_archive');

function better_editions_archive( $query ) {

    if ( $query->is_tax( 'edition' ) && $query->is_main_query() ) {
        $terms = get_terms( 'edition', array( 'fields' => 'ids' ) );
        $query->set( 'post_type', array( 'post' ) );
        $query->set( 'tax_query', array(
            'relation' => 'OR',
            array(
                'taxonomy' => 'edition',
                'field' => 'id',
                'terms' => $terms,
                'operator' => 'NOT IN'
            )
        ) );
    }

    return $query;
}
share|improve this answer
    
Just tried that. It didn't change anything. No debug errors/suggestions either. Thanks for trying. :) –  its_me Mar 12 '13 at 19:44
    
As a debugging method, you can try print_r($query) on your first sample code. Somewhere in the output there should be the SQL being generated. Add it here, it might be useful. –  vancoder Mar 12 '13 at 20:25
    
Jsut to check - you are on WP 3.5 +, right? –  vancoder Mar 12 '13 at 20:34
    
Yes, the latest version of WordPress (always!). And for the debug, you want me to replace return $query; with print_r($query);? Is that what you want me to do? –  its_me Mar 12 '13 at 20:38
    
If yes, here's what I got: paste.kde.org/694496 -- Does that say something? (I didn't understand it.) –  its_me Mar 12 '13 at 20:39
show 2 more comments

Note to self: @vancoder's answer is basically a better (& automated) version of this:

add_filter('pre_get_posts','better_editions_archive');

function better_editions_archive($query) {

    if ( $query->is_tax( 'edition') && $query->is_main_query() ) {

        $query->set( 'post_type', array( 'post' ) );

        $query->set( 'tax_query',
            array(
                array(
                    'taxonomy' => 'edition',
                    'field' => 'id',
                    'terms' => array( 6, 7, 8 ),
                    'operator' => 'NOT IN'
                )
            )
        );

    }

    return $query;
}

(What the code says) If it's the archive for any term that belongs to the custom taxonomy 'edition', then...

  1. The code doesn't mess with the default function of the terms' archive pages, i.e., posts assigned to a term of the custom taxonomy 'edition' will (as usual) be shown in the relevant term's archive.

  2. But if a post is not assigned to any of the given custom taxonomy's terms (see 'terms' => array( 6, 7, 8 ) and 'operator' => 'NOT IN'), then show such posts in the archive pages of all the terms of the custom taxonomy.

  3. The code also affects the feeds of the said terms, and therefore, the feeds mirror the content of archive pages, which is just what I need. In case you don't want the feeds to be affected i.e. if you want the changes to only apply to the archive pages replace the IF with this:

    if ( $query->is_tax( 'edition') && $query->is_main_query() && ! $query->is_feed() ) {
    
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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