Wordpress - Getting the Intersection of Two Custom Taxonomy Terms for a Custom Post Type?
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
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
.