Custom Taxonomy and Tax_Query

First of all, you run register_post_type on init and register_taxonomy on after_setup_theme which is called after init. This means your custom taxonomy will not be available when registering the post type. I would suggest you remove the taxonomies keyword from the register_post_type arguments array, and just register the taxonomy manually afterwards. In your example code it looks like you are creating the post type-taxonomy link twice.

I am also not sure about 'query_var' => true, in the register_taxonomy arguments array. The documentation says you can set it to false, or a string, but does not state what will happen if you set it to true. Hopefully WordPress will be smart enough to substitute it with something more useful, but since you are not explicitly setting it to something other than your taxonomy name just remove it for now (that means talktype will be used instead).

I just put this in an empty theme and it appears to be working fine (i.e. it prints a SQL query including the meta query). Actually running a query instead works fine too:

functions.php

// Add post types of "Talk" and "Event"
function nc_custom_post_types() {
    register_post_type( 'talk',
        array(
            'labels' => array(
                'name' => __( 'Talks' ),
                'singular_name' => __( 'Talk' )
            ),
            'public' => true,
            'has_archive' => true,
        )
    );


    // Add new "talktype" taxonomy to "talk" post type
    register_taxonomy('talktype', 'talk', array(
        'hierarchical' => true,
        // This array of options controls the labels displayed in the WordPress Admin UI
        'labels' => array(
            'name' => _x( 'Talk Types', 'taxonomy general name' ),
            'singular_name' => _x( 'Talk Type', 'taxonomy singular name' ),
            'search_items' =>  __( 'Search Talk Types' ),
            'all_items' => __( 'All Talk Types' ),
            'parent_item' => __( 'Parent Talk Type' ),
            'parent_item_colon' => __( 'Parent Talk Type:' ),
            'edit_item' => __( 'Edit Talk Type' ),
            'update_item' => __( 'Update Talk Type' ),
            'add_new_item' => __( 'Add New Talk Type' ),
            'new_item_name' => __( 'New Talk Type Name' ),
            'menu_name' => __( 'Talk Types' ),
        ),
        // Control the slugs used for this taxonomy
        'rewrite' => array(
            'slug' => 'talktype',
            'with_front' => false, // Don't display the category base before "/locations/"
            'hierarchical' => true // This will allow URL's like "/locations/boston/cambridge/"
        ),
    ));
}
add_action( 'init', 'nc_custom_post_types' );

/* For testing purposes
add_action('wp', 'test');
function test() {

    $nextSundayTalkArgs = array(
        'post_type' => 'talk',
        'posts_per_page' => 1,
        'tax_query' => array(
            array(
                'taxonomy' => 'talktype',
                'field' => 'slug',
                'terms' => 'sunday-talk'
            )
        )
    );
    $nextSundayTalkQuery = new WP_Query( $nextSundayTalkArgs );

    var_dump($nextSundayTalkQuery->request);
    die();
}
*/

function sunday_query_args() {

    $nextSundayTalkArgs = array(
        'post_type' => 'talk',
        'posts_per_page' => 1,
        'tax_query' => array(
            array(
                'taxonomy' => 'talktype',
                'field' => 'slug',
                'terms' => 'sunday-talk'
            )
        )
    );

    return $nextSundayTalkArgs;
}

index.php

<?php get_header(); ?>
<?php query_posts(sunday_query_args()); ?>
<div id="content">
    <?php while ( have_posts() ) : the_post(); ?>    
         <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <h1 class="entry-title"><?php the_title(); ?></h1>
            <div class="entry-content">
                <?php the_content(); ?>
            </div>
        </article>
    <?php endwhile; ?>
</div>
<?php get_sidebar(); ?>
<?php get_footer(); ?>

EDIT: Just tried running your code unmodified, and that actually works as well. As far as I can tell, the 0 = 1 bit in the SQL is generated when either the taxonomy or term specified is not found, which means the INNER JOIN can not be created. Make sure you have the term in your database, and that both term and taxonomy shows up in the edit screen of your post type.

I know you have checked and double-checked the term contents of your database, so if this still does not solve your issue try to isolate the problem further. Start by using a clean WordPress installation adding only the code I supplied above, adding a talk post and assigning it the sunday-talk term. That works fine when I try it. Also try, manually running the SQL directly on you database, if that does not work you it’s safe to say that the post/term relation does not exist. The resulting SQL query should look something like this (be sure change the value of wp_term_relationships.term_taxonomy_id though):

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID FROM wp_posts  INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1  AND ( wp_term_relationships.term_taxonomy_id IN (4) ) AND wp_posts.post_type="talk" AND (wp_posts.post_status="publish") GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 1

Leave a Comment