3

I have a custom post with a taxonomy associated to it. That taxonomy only has one term, and posts either belong to it or not, in a boolean fashion.

On the search results, I wish to show the custom posts that belong to the taxonomy, and not show the ones that don't belong. I've thought of two ways of accomplishing this, but I'm not sure which one is the best:

  • include only custom posts that belong to the taxonomy term;
  • exclude all custom posts that don't belong to the taxonomy term.

I've managed to do the exact opposite from what I want, with the following code:

global $query_string;
$query_args = explode("&", $query_string);
$search_query = array();
foreach($query_args as $key => $string) {
    $query_split = explode("=", $string);
    $search_query[$query_split[0]] = urldecode($query_split[1]);
}

$custom_query = array();
$custom_query['tax_query'][] = array( 'taxonomy' => 'tax-whatever', 'terms' => array('term-whatever'), 'field' => 'slug', 'operator' => 'NOT IN' );
$args = array_merge( $wp_query->query, $custom_query );
query_posts( $args );

$search = new WP_Query($search_query);

This, of course, outputs all the custom posts which are NOT IN the term-whatever. How can I accomplish the exact opposite?

EDIT

I will try to explain my problem a bit better. Let's use an example.

Imagine I have a taxonomy which is called "Selected" and only one taxonomy term called "Yes" that users can choose with a checkbox. I suppose I should have used two checkboxes ("Yes" and "No"), but I thought it didn't make much sense at the time.

When users search for something in the website, all pages, posts and custom posts appear in the results. The only thing I want to remove from the search results are the custom posts that are not associated with the taxonomy term "Yes", leaving all the rest like it is. This means I want to output all pages, posts and "Yes" custom posts.

Any ideas how I can achieve this? Thanks.

UPDATE

Here's an idea I had: Is there any way I can make two queries and merge the results?

  • One query with all the posts and pages except the custom post ('exclude_from_search' => true);
  • Other query with only the custom posts that match the taxonomy term ($custom_query['tax_query'][] = array( 'taxonomy' => 'tax-whatever', 'terms' => array('term-whatever'), 'field' => 'slug', 'operator' => 'IN' );).

However, if I use something like:

$mergedposts = array_merge( $wp_query->query, $custom_query );
query_posts( $mergedposts );

It will only show me the custom posts.

I suppose I could make a direct query with SQL but I've never worked with it. Although that is something I wish to learn in the future, right now it doesn't seem like a good way to solve this kind of problem, since I won't understand what I'm doing.

Right now my best option so far is create a new taxonomy term and classify all the "uncategorized" custom posts with it. However, they are a few hundreds, so it will take a while.

NEW UPDATE

I found a way to detect if a custom post belongs to a specific term in a taxonomy. This is a piece of code I picked up somewhere, since I don't have the PHP knowledge to create something like this all by myself. However, I understand what's being done and I adapted it to my situation.

function is_selected( $selected, $_post = null ) {
    if ( empty( $selected ) )
        return false;

    if ( $_post )
        $_post = get_post( $_post );
    else
        $_post =& $GLOBALS['post'];

    if ( !$_post )
        return false;

    $r = is_object_in_term( $_post->ID, 'selected', $selected );

    if ( is_wp_error( $r ) )
        return false;

    return $r;
}

This function will work correctly but only if used inside the loop. However, if I change the loop after the search query is made, it can mess up the pagination, and the number of results found will possibly be wrong.

Not sure if this is a step in the right direction, but at least it's a step.

3
  • change 'operator' => 'NOT IN' to 'operator' => 'IN' Oct 16, 2012 at 11:11
  • That will, of course, only show custom posts and hide all the rest. That's not what I'm looking for.
    – Cthulhu
    Oct 16, 2012 at 11:13
  • 1
    Just a thought, when attaching information like this to a post(a yes/no), in my experience its better to store this information in the postmeta table. I don't necessarily have the full picture so that might not have been the better solution, but querying for this information on postmeta would have made for a much easier and simpler query
    – Macgyver
    Oct 18, 2012 at 14:32

1 Answer 1

6
+50

After reading your revised question it was easier to comprehend what you are trying to do. My new solution looks like the thing you wanted to do in the first place: it just excludes all posts which are of your custom type but don't have the "yes"-term associated with it:

$custom_query = array();
$custom_query['post_type'] = 'any';

// first, query all the posts of your custom type
// that don't have the "yes"-term:
$tmp_wp_query = new WP_Query(array(
    'posts_per_page' => -1,
    'fields' => 'ids',
    'post_type' => 'your-post-type',
    'tax_query' => array(array(
        'taxonomy' => 'tax-whatever', 'terms' => array('term-whatever'),
        'field' => 'slug', 'operator' => 'NOT IN'
    ))
));

if(!empty($tmp_wp_query->posts)) {
    // Exclude the "yes"-less posts from the actual post query
    $custom_query['post__not_in'] = $tmp_wp_query->posts;
}

// now proceed with your original code and execute the definitive query
$args = array_merge( $wp_query->query, $custom_query );
query_posts( $args );

$search = new WP_Query($search_query);

The only downside is, that there are now two queries to run. But the first query is relatively light-weight so the performance-loss should not be that huge.

3
  • Thank you for your help, but I guess I didn't explain myself very well. I edited my question with an example.
    – Cthulhu
    Oct 17, 2012 at 9:36
  • @Cthulhu: thanks for your response - I have now revised my answer.
    – vstm
    Oct 19, 2012 at 16:52
  • That was absolutelly perfect. Thank you very much!
    – Cthulhu
    Oct 22, 2012 at 9:23

Your Answer

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

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