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.

When I try to get an archive for a custom taxonomy, WP searches for a page and doesn’t find anything.

The Setup

My code from the functions.php:

add_action( 'init', 'register_store_taxonomy' );

function register_store_taxonomy()
{
    $args = array (
        'hierarchical'      => TRUE
    ,   'label'             => 'Store'
    ,   'public'            => TRUE
    ,   'query_var'         => 'store'
    ,   'rewrite'           => TRUE
    ,   'show_in_nav_menus' => TRUE
    ,   'show_ui'           => TRUE
    );
    register_taxonomy(
            'store'
        ,   array ( 'post', 'page' )
        ,   $args
        );
}

Now I have a post tagged with store itunes. Clicking on the link to /store/mac-store/ should list all post in this taxonomy. And it does! On a local server (Win7).
On the staging server (Debian with mostly identical settings), however, I get the 404 page (and the 404 status header).

There are no pages with similar names or slugs, not even in trash. I’ve refreshed the permalinks several times. No active plugins. I tried Google but couldn’t find anything useful.

Debugging

I added the following code to my functions.php to track the error:

add_action( 'wp_footer', 'dump_query' );
function dump_query()
{
    if ( current_user_can( 'edit_posts' ) )
    {
        pre_dump( $GLOBALS['wp_query'] );
    }
}

function pre_dump( $var, $print = TRUE )
{
    $out = '<pre class="vardump">' . htmlspecialchars( var_export( $var, TRUE ) ) . '</pre>';

    if ( ! $print )
        return $out;

    print $out;
}

Output local, working query

WP_Query::__set_state(array(
   'query_vars' => 
  array (
    'store' => 'itunes',
    'error' => '',
    'm' => 0,
    'p' => 0,
    'post_parent' => '',
    'subpost' => '',
    'subpost_id' => '',
    'attachment' => '',
    'attachment_id' => 0,
    'name' => '',
    'static' => '',
    'pagename' => '',
    'page_id' => 0,
    'second' => '',
    'minute' => '',
    'hour' => '',
    'day' => 0,
    'monthnum' => 0,
    'year' => 0,
    'w' => 0,
    'category_name' => '',
    'tag' => '',
    'cat' => '',
    'tag_id' => '',
    'author_name' => '',
    'feed' => '',
    'tb' => '',
    'paged' => 0,
    'comments_popup' => '',
    'meta_key' => '',
    'meta_value' => '',
    'preview' => '',
    's' => '',
    'sentence' => '',
    'fields' => '',
    'category__in' => 
    array (
    ),
    'category__not_in' => 
    array (
    ),
    'category__and' => 
    array (
    ),
    'post__in' => 
    array (
    ),
    'post__not_in' => 
    array (
    ),
    'tag__in' => 
    array (
    ),
    'tag__not_in' => 
    array (
    ),
    'tag__and' => 
    array (
    ),
    'tag_slug__in' => 
    array (
    ),
    'tag_slug__and' => 
    array (
    ),
    'meta_query' => 
    array (
    ),
    'ignore_sticky_posts' => false,
    'suppress_filters' => false,
    'cache_results' => true,
    'update_post_term_cache' => true,
    'update_post_meta_cache' => true,
    'post_type' => '',
    'posts_per_page' => 10,
    'nopaging' => false,
    'comments_per_page' => '50',
    'no_found_rows' => false,
    'taxonomy' => 'store',
    'term' => 'itunes',
    'order' => 'DESC',
    'orderby' => 'wp_posts.post_date DESC',
  ),
   'tax_query' => 
  WP_Tax_Query::__set_state(array(
     'queries' => 
    array (
      0 => 
      array (
        'taxonomy' => 'store',
        'terms' => 
        array (
          0 => 'itunes',
        ),
        'include_children' => true,
        'field' => 'slug',
        'operator' => 'IN',
      ),
    ),
     'relation' => 'AND',
  )),
   'post_count' => 1,
   'current_post' => -1,
   'in_the_loop' => false,
   'comment_count' => 0,
   'current_comment' => -1,
   'found_posts' => '1',
   'max_num_pages' => 1,
   'max_num_comment_pages' => 0,
   'is_single' => false,
   'is_preview' => false,
   'is_page' => false,
   'is_archive' => true,
   'is_date' => false,
   'is_year' => false,
   'is_month' => false,
   'is_day' => false,
   'is_time' => false,
   'is_author' => false,
   'is_category' => false,
   'is_tag' => false,
   'is_tax' => true,
   'is_search' => false,
   'is_feed' => false,
   'is_comment_feed' => false,
   'is_trackback' => false,
   'is_home' => false,
   'is_404' => false,
   'is_comments_popup' => false,
   'is_paged' => false,
   'is_admin' => false,
   'is_attachment' => false,
   'is_singular' => false,
   'is_robots' => false,
   'is_posts_page' => false,
   'is_post_type_archive' => false,
   'parsed_tax_query' => true,
   'query' => 
  array (
    'store' => 'itunes',
  ),
   'request' => ' SELECT SQL_CALC_FOUND_ROWS  wp_posts.* 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 (135,134,133,132,131,130,129,128,125) ) AND wp_posts.post_type IN (\'post\', \'page\', \'attachment\') AND (wp_posts.post_status = \'publish\' OR wp_posts.post_author = 7 AND wp_posts.post_status = \'private\') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 10',
   'posts' => 
  array ( /* cut out */),
   'queried_object' => 
  stdClass::__set_state(array(
     'term_id' => '124',
     'name' => 'iTunes',
     'slug' => 'itunes',
     'term_group' => '0',
     'term_taxonomy_id' => '125',
     'taxonomy' => 'store',
     'description' => '',
     'parent' => '0',
     'count' => '1',
  )),
   'queried_object_id' => 124,
))

Output staging server, broken query

WP_Query::__set_state(array(
   'query_vars' => 
  array (
    'page' => 0,
    'pagename' => 'itunes',
    'error' => '',
    'm' => 0,
    'p' => 0,
    'post_parent' => '',
    'subpost' => '',
    'subpost_id' => '',
    'attachment' => '',
    'attachment_id' => 0,
    'name' => 'itunes',
    'static' => '',
    'page_id' => 0,
    'second' => '',
    'minute' => '',
    'hour' => '',
    'day' => 0,
    'monthnum' => 0,
    'year' => 0,
    'w' => 0,
    'category_name' => '',
    'tag' => '',
    'cat' => '',
    'tag_id' => '',
    'author_name' => '',
    'feed' => '',
    'tb' => '',
    'paged' => 0,
    'comments_popup' => '',
    'meta_key' => '',
    'meta_value' => '',
    'preview' => '',
    's' => '',
    'sentence' => '',
    'fields' => '',
    'category__in' => 
    array (
    ),
    'category__not_in' => 
    array (
    ),
    'category__and' => 
    array (
    ),
    'post__in' => 
    array (
    ),
    'post__not_in' => 
    array (
    ),
    'tag__in' => 
    array (
    ),
    'tag__not_in' => 
    array (
    ),
    'tag__and' => 
    array (
    ),
    'tag_slug__in' => 
    array (
    ),
    'tag_slug__and' => 
    array (
    ),
    'ignore_sticky_posts' => false,
    'suppress_filters' => false,
    'cache_results' => true,
    'update_post_term_cache' => true,
    'update_post_meta_cache' => true,
    'post_type' => '',
    'posts_per_page' => 10,
    'nopaging' => false,
    'comments_per_page' => '50',
    'no_found_rows' => false,
    'order' => 'DESC',
    'orderby' => 'wp_posts.post_date DESC',
  ),
   'tax_query' => 
  WP_Tax_Query::__set_state(array(
     'queries' => 
    array (
    ),
     'relation' => 'AND',
  )),
   'post_count' => 0,
   'current_post' => -1,
   'in_the_loop' => false,
   'comment_count' => 0,
   'current_comment' => -1,
   'found_posts' => 0,
   'max_num_pages' => 0,
   'max_num_comment_pages' => 0,
   'is_single' => false,
   'is_preview' => false,
   'is_page' => false,
   'is_archive' => false,
   'is_date' => false,
   'is_year' => false,
   'is_month' => false,
   'is_day' => false,
   'is_time' => false,
   'is_author' => false,
   'is_category' => false,
   'is_tag' => false,
   'is_tax' => false,
   'is_search' => false,
   'is_feed' => false,
   'is_comment_feed' => false,
   'is_trackback' => false,
   'is_home' => false,
   'is_404' => true,
   'is_comments_popup' => false,
   'is_paged' => false,
   'is_admin' => false,
   'is_attachment' => false,
   'is_singular' => false,
   'is_robots' => false,
   'is_posts_page' => false,
   'is_post_type_archive' => false,
   'parsed_tax_query' => true,
   'query' => 
  array (
    'page' => '',
    'pagename' => 'store/itunes',
  ),
   'request' => ' SELECT   wp_posts.* FROM wp_posts  WHERE 1=1  AND (wp_posts.ID = \'0\') AND wp_posts.post_type = \'page\'  ORDER BY wp_posts.post_date DESC ',
   'posts' => 
  array (
  ),
   'queried_object' => NULL,
   'queried_object_id' => 0,
))

I feel that I miss something obvious, but I’m lost right now.

So my questions are: How can I make WP search the taxonomy archive? Why does it work on one server, but not on the other?

Update

Permalinks are set to /%year%/%postname%/ on both servers and I flushed the rewrite rules on init per:

$GLOBALS['wp_rewrite']->flush_rules();

Update 2

using the Rewrite Analyzer plugin from @Jan Fabry I compared the rules on my local installation and on the staging server. On the latter, the rules are absent.

Rewrite rules local

store/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$            store: ([^/]+)
           feed: (feed|rdf|rss|rss2|atom)
store/([^/]+)/(feed|rdf|rss|rss2|atom)/?$             store: ([^/]+)
           feed: (feed|rdf|rss|rss2|atom)
store/([^/]+)/page/?([0-9]{1,})/?$            store: ([^/]+)
          paged: ([0-9]{1,})
store/([^/]+)/?$              store: ([^/]+)

Do I really have to add the rules manually? Usually register_taxonomy() should do that, shouldn’t it?

Workaround

Bah! I used a workaround to add the missing rewrite rules per functions.php:

add_action( 'init', 'add_taxrules_manually' );
function add_taxrules_manually()
{
    $tax           = 'store';
    $rewrite_rules = get_option( 'rewrite_rules' );

    if ( isset ( $rewrite_rules[ $tax . '/([^/]+)/?$' ] ) )
    {
        return;
    }

    $new_rules = array (
        $tax . '/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?' . $tax . '=$matches[1]&feed=$matches[2]',
        $tax . '/([^/]+)/(feed|rdf|rss|rss2|atom)/?$'      => 'index.php?' . $tax . '=$matches[1]&feed=$matches[2]',
        $tax . '/([^/]+)/page/?([0-9]{1,})/?$'             => 'index.php?' . $tax . '=$matches[1]&paged=$matches[2]',
        $tax . '/([^/]+)/?$'                               => 'index.php?' . $tax . '=$matches[1]',
    );

    $update = array_merge( $new_rules, $rewrite_rules );
    update_option( 'rewrite_rules', $update );
}

Important: The new rules must come before the page rules. Changing the order of arguments in array_merge() will not fix it.

The question is still open, because I just have to understand what happens here.

share|improve this question
    
The taxonomy is not being set in the second dump. Does your theme have a taxonomy template for store? Are permalinks set to the same on both installations? Does either installation have any pages with a similar name to the taxonomy? Have you tested using another theme? –  t31os Mar 21 '11 at 9:28
    
No, there are no pages with similar names, and the theme doesn’t change anything: I put the registration hooks and functions into a plugin and tested TwentyTen – same result. –  toscho Mar 21 '11 at 9:59
    
Tried another permalink structure? Tried default? Just to rule out a permalink issue/conflict. –  t31os Mar 21 '11 at 10:04
    
The default rules without pretty permalinks work just fine. mod_rewrite is on too. –  toscho Mar 21 '11 at 10:23
    
I suppose the question now is, why are the rules not generated on the staging server... –  t31os Mar 21 '11 at 12:06
show 5 more comments

1 Answer

up vote 0 down vote accepted

Did you flush the rewrite rules?

share|improve this answer
    
Yes, per backend and per script. I made an update to my question. –  toscho Mar 21 '11 at 9:49
1  
Ok. The wp_query dumps are not relevant. $GLOBALS['wp']->matched_rule and $wp_rewrite->rules are what you want. –  scribu Mar 21 '11 at 11:40
1  
Easy to get at that with Debug Bar installed, matched rule(amongst other things) are listed in the request tab. Though i think at this point it's safe to say the problem has been identified as being rules not getting into the rewrite array. –  t31os Mar 21 '11 at 12:28
    
This is late, but … another plugin flushed the rules on every request, so I’ll mark it as answer. :) –  toscho Dec 30 '11 at 11:47
add comment

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.