WordPress 3.0 custom queries, post types and taxonomies

There’s been a few really great articles recently published about the new custom posts features in the WordPress 3 Beta, most notably Justin Tadlock’s excellent article and an equally enlightening post on wpengineer.com. I’ve had some fun experimenting a little with the new possibilities opened up to me with this new functionality but I very quickly came up with a problem that took quite a bit of head scratching to solve, namely how to filter my query to a custom post type by taxonomy – akin to displaying all the blog posts within a specific category, I wanted to be able to display all my custom posts in my custom taxonomy (read category).

Using code grabbed from the above articles and the codex I had successfully created a new custom post type. Here’s the code for your functions.php file. As per the codex example, let’s call it ‘books’.

function new_post_type() {
register_post_type( 'books',
array(
'labels' => array(
'name' => __( 'Books' ),
'singular_name' => __( 'Book' )
),
'public' => true,
)
);
}
add_action( 'init', 'new_post_type' );

All of this functionality is clearly explained in either of the articles I mentioned (as well as a more detailed discussion of the various options –┬áthe purpose of this article is just to demonstrate how to perform a custom query on a new custom post type with a custom taxonomy.

Right, now I can retrieve my new post type by passing the following parameter to the query. This code should be placed outside of the loop (it’s a loop itself!) in whichever page you’d like it to appear.

<?php
$yell = new WP_Query(array('post_type' => 'books'));
while ($yell->have_posts()) : $yell->the_post();
?>

<h2><?php the_title(); ?></h2>

<?php the_content(); ?>

<?php endwhile; wp_reset_query(); ?>

Now, I want to add a custom taxonomy to my custom post type: I want to do is to be able to categorize books by genre. I can do this by adding the following code to my functions.php file:

function create_book_taxonomies() {
// Add new taxonomy, make it hierarchical (like categories)
$labels = array(
'name' => _x( 'Genres', 'taxonomy general name' ),
'singular_name' => _x( 'Genre', 'taxonomy singular name' ),
'search_items' => __( 'Search Genres' ),
'popular_items' => __( 'Popular Genres' ),
'all_items' => __( 'All Genres' ),
'parent_item' => __( 'Parent Genres' ),
'parent_item_colon' => __( 'Parent Genre' ),
'edit_item' => __( 'Edit Genre' ),
'update_item' => __( 'Update Genre' ),
'add_new_item' => __( 'Add New Genre' ),
'new_item_name' => __( 'New Genre Name' ),
);
register_taxonomy('Genres',array('books'), array(
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'genres' )
));
}
add_action( 'init', 'create_book_taxonomies', 0 );

Awesome – now I can add a new ‘genre’ to my books – this is akin to adding a new category to your posts. Let’s say that I now add 2 genres: ‘sci fi’ and ‘thriller’. I can now filter my query to query one of my newly created genres.

<?php
$yell = new WP_Query(array('post_type' => 'books', 'genres' => 'sci fi'));
while ($yell->have_posts()) : $yell->the_post();
?>

<h2><?php the_title(); ?></h2>

<?php the_content(); ?>

<?php endwhile; wp_reset_query(); ?>

At the moment it seems that you can’t filter the query further (as you can for posts) by adding an equivalent to:

'category__in' => array(2,6)

Namely:

'genres__in' => array(2,5)

Which seems – to me at least – a real missed opportunity (it never made it into the core, I’m told), but there may yet be some crafty plug-in authors with a work-around. Here’s hoping!