Wordpress - Custom Taxonomy WP_Query for All Terms in a Taxonomy?
I encountered a similar situation Dave. This code did the trick for my purposes. It's not the leanest option in the world but it does the job well:
// Get all term ID's in a given taxonomy
$taxonomy = 'taxonomy_name';
$taxonomy_terms = get_terms( $taxonomy, array(
'hide_empty' => 0,
'fields' => 'ids'
) );
// Use the new tax_query WP_Query argument (as of 3.1)
$taxonomy_query = new WP_Query( array(
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'id',
'terms' => $taxonomy_terms,
),
),
) );
Hopefully this help you or anyone else experiencing the issue.
Kevin
Something like this might work:
$args = array( 'post_type' => 'post', 'tax_query' => array( array( 'taxonomy' => 'your_custom_taxonomy', 'operator' => 'EXISTS' ), ), ); $query = new WP_Query( $args );
You are basically asking for any post assigned to any term within your_custom_taxonomy.
Hi @Dave Morris:
You are correct, WordPress decides if you don't have a term they'll just ignore your taxonomy.
There are three (3) main approaches you could try:
Use a complete SQL query with
$wpdb->get_results()
,Get a list of
$post->ID
s for all posts in your taxonomy and then pass them using the'post__id'
argument, orAnnotate the SQL used by
WP_Query
with one of the hooks that let's you add a SQLINNER JOIN
referencing the taxonomy tables.
I try to avoid complete SQL in WordPress until either it can't be helped or it's simply returning a list of IDs. And in this case I'd avoid pulling a list of $post-ID
s for use with the 'post__id'
argument because it could run into performance issues and even memory problems if you had lots of posts. So that leaves us with #3.
I've created a class to extend WP_Query
called PostsByTaxonomy
which uses the 'posts_join
' hook. You can see it here:
class PostsByTaxonomy extends WP_Query {
var $posts_by_taxonomy;
var $taxonomy;
function __construct($args=array()) {
add_filter('posts_join',array(&$this,'posts_join'),10,2);
$this->posts_by_taxonomy = true;
$this->taxonomy = $args['taxonomy'];
unset($args['taxonomy']);
parent::query($args);
}
function posts_join($join,$query) {
if (isset($query->posts_by_taxonomy)) {
global $wpdb;
$join .=<<<SQL
INNER JOIN {$wpdb->term_relationships} ON {$wpdb->term_relationships}.object_id={$wpdb->posts}.ID
INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id={$wpdb->term_relationships}.term_taxonomy_id
AND {$wpdb->term_taxonomy}.taxonomy='{$this->taxonomy}'
SQL;
}
return $join;
}
}
You would call this class as you see below. The argument 'taxonomy'
is an required but you can pass any (all?) of the other parameters that WP_Query
expects as well, such as 'posts_per_page'
:
$query = new PostsByTaxonomy(array(
'taxonomy' => 'category',
'posts_per_page' => 25,
));
foreach($query->posts as $post) {
echo " {$post->post_title}\n";
}
You can copy the PostsByTaxonomy
class to your theme's functions.php
file, or you can use it within a .php
file of a plugin you may be writing.
If you want to test it quickly I've posted a self-contained version of the code to Gist which you can download and copy to your web server's root as test.php
, modify for your use case, and then request from your browser using a URL like http://example.com/test.php
.
UPDATE
To omit Sticky Posts from the posts included in the query, try this:
$query = new PostsByTaxonomy(array(
'taxonomy' => 'category',
'posts_per_page' => 25,
'caller_get_posts' => true,
));
Or if it is important to you that the PostsByTaxonomy
class never include sticky posts you could put it into the constructor:
function __construct($args=array()) {
add_filter('posts_join',array(&$this,'posts_join'),10,2);
$this->posts_by_taxonomy = true;
$this->taxonomy = $args['taxonomy'];
$args['caller_get_posts'] = true // No Sticky Posts
unset($args['taxonomy']);
parent::query($args);
}
UPDATE 2
After posting the above I learned 'caller_get_posts' will be deprecated and 'ignore_sticky_posts'
will be used in WordPress 3.1.