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.

(Moderators note: Was originally titled "How to get_posts of a custom post type that is in two custom taxonomies?")

I have a custom post type that has two taxonomies which are separate, one called "Project Type" and one called "Package". I need to get a list of projects which are of "Project Type" A and "Package" A. I tried using following code:

$args = array(
  'post_type' => 'portfolio', 
  'numberposts' => -1, 
  'project_type' => 'A', 
  'package' => 'A'
); 
$my_posts = get_posts($args);  

But this gets all the posts that are EITHER in Project Type A OR Package A.

Is there any way to say in get_posts() that I want to return only those posts that are in BOTH taxonomies?

share|improve this question

3 Answers 3

up vote 4 down vote accepted

As of v1.3, the Query Multiple Taxonomies plugin works great with WP_Query. Your original args work as is.

$args = array(
'post_type' => 'portfolio',
'numberposts' => -1,
'project_type' => 'A',
'package' => 'A'
);

Then make a new query and check it:

$foo = new WP_Query($args);
var_dump($foo->posts);

I tested this on my own custom taxonomy setup, and it only returned posts which matched both terms in the query.

Another convenient method of grabbing multiple taxonomy terms with QMT is building simple URL queries:

site.com/?post_type=portfolio&package=foo&project=bar

I've used this method with the add_query_args() function to create links on a page that modify the current query, refining it by adding additional terms and taxonomies. The syntax also works great with a search input, as multiple words in the input field are posted as foo+bar, which works great with QMT:

site.com/?post_type=portfolio&project=alpha&colors=red+blue+green

Which returns only posts that meet all these criteria - Type: Portfolio / Project: Alpha / Colors: red + blue + green

share|improve this answer

Hi @shaun:

@Rarst is right in that they are adding this functionality to WordPress v3.1, but it won't be here for a while and I'm sure you need it now. You could try to grab the code they are working on and try to make it work, you could use the plugin both @Rarst and @somatic mention, or you could just include the code you need into your theme, below.

The following code is a posts_where hook to add a tax_terms query variable with a value of the format (i.e. colon-commas) where the values are term slugs:

"{$varname1}:{$value1},{$varname2}:{$value2},...{$varnameN}:{$valueN}"

This is a self-contained .php you can drop into the root of your website to test it out before pulling the add_action call and the tax_terms_where() function into your theme's functions.php file (or into the .php file of one of your own plugins.)

<?php
/*
* Adds "tax_terms" to WP_Query()
*
* See: http://lists.automattic.com/pipermail/wp-hackers/2010-October/035258.html
* See: http://wordpress.stackexchange.com/questions/2255/
*
*/

  header('Content-Type:text/plain');
  include "wp-load.php";
  add_action('posts_where','tax_terms_where',10,2);

  $result = new WP_Query('post_type=portfolio&tax_terms=project_type:A,package:A');
  foreach($result->posts as $post) {
    echo "{$post->post_title}\n";
  }

function tax_terms_where($where,$wp_query) {
  if (isset($wp_query->query)) {
    $query = $wp_query->query;
    if (is_string($query))
      parse_str($query,$query);
    if (is_array($query) && isset($query['tax_terms'])) {
      global $wpdb;
      $tax_terms = explode(',',$query['tax_terms']);
      foreach($tax_terms as $tax_term) {
        list($taxonomy,$term) = explode(':',$tax_term);
        $sql = <<<SQL
AND $wpdb->posts.ID IN (
  SELECT tr.object_id
  FROM $wpdb->term_relationships AS tr
  INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
  INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id
  WHERE tt.taxonomy='%s' AND t.slug='%s'
)
SQL;
        $where .= $wpdb->prepare($sql,$taxonomy,$term);
      }
    }
  }
  return $where;
}

If this isn't exactly what you need because, for example, you'd rather match the $term->term_id instead of matching the $term->slug then the code shouldn't be too hard to modify for your needs, assuming you are comfortable with SQL and .php.

share|improve this answer

Usual disclaimer - I hadn't messed with custom stuff myself so far.

I think complex taxonomy queries are not implemented in WP core (yet). Try Query Multiple Taxonomies plugin.

share|improve this answer
    
Hmm.. initial testing with this has shown that it is not working. Not sure if it is because I am using get_posts ? –  Shaun Sep 27 '10 at 15:01
    
get_posts() and query_posts() accept same parameters so it should be fine. –  Rarst Sep 27 '10 at 15:14

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.