Question

I've created a custom taxonomy "foo" with rewrite slug "foo" and query_var "foo".

Say for example, I also have terms "bar" and "baz" in the "foo" taxonomy.

At the moment, permalinks like /foo/bar and /foo/baz work fine, using my taxonomy-foo.php template.

What I'd like to do is be able to hit /foo and retrieve all posts with a link to any "foo" taxonomy. Currently, this URL shows a 404.

How can I achieve this? If I can somehow hook into the rewrite code and set a default term value ('all' for example) if missing, that might be a way to move forward but I'm not sure if this is possible.

I'd preferably like to use the taxonomy-foo.php template file for the "catch all", dealing with the logic of showing posts from one or all terms in there.

Cheers

Edit: I've figured how to catch a request for /foo and set some defaults using add_filter('request', ...) though I had to use an existing term as using anything else generates a 404. Is there any way to avoid this limitation?

Was it helpful?

Solution

What you want is an index page for custom taxonomies. There is a ticket for that, but it's not clear what is the most obvious thing to show on this page: 1) a list of all posts attached to any term of that taxonomy, or 2) a list of all terms of this taxonomy? Remember that category is also a taxonomy, but it is assumed that all posts fall under at least one category (with Uncategorized as the default). In that case, option 1 would be the same as the regular post query, and option 2 might make more sense.

The related issue of an index page for custom post types will be fixed in the upcoming 3.1 release.

I tried something myself, and instead of interfering with the request hook, I think the better way to do this is adding a new rewrite rule and modifying the query:

add_action( 'init', 'wpse4663_init' );
function wpse4663_init()
{
    // The custom taxonomy rewrite rules end up at the top of the rewrite array
    register_taxonomy(
        'wpse4663',
        array( 'post' ),
        array(
            'label' => 'WPSE 4663',
        )
    );

    // So there probably is no danger in adding this specific rewrite rule there too
    // We re-use the existing `taxonomy` query var, but with no `term`
    // We clean this up in `parse_query`, otherwise get_posts() complains
    // You could make this work for all taxonomies (categories, tags, ...) by doing this repeatedly
    // But then it's probably better to do this in the `rewrite_rules_array` filter
    add_rewrite_rule( 'wpse4663(/page/([0-9]+))?/?$', 'index.php?taxonomy=wpse4663&paged=$matches[2]', 'top' );
}

add_filter( 'parse_query', 'wpse4663_parse_query' );
function wpse4663_parse_query( &$wp_query )
{
    // is_tax is only true if both a taxonomy and a term are set, otherwise is_home is true
    // But we don't want that: is_tax and is_archive should be true, is_home should be false
    if ( !$wp_query->is_tax && $taxonomy_query = $wp_query->get( 'taxonomy' ) ) {
        foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy => $t ) {
            if ( $t->query_var && $taxonomy_query == $t->query_var ) {
                // Make sure the conditional tags work, so the right template is loaded
                $wp_query->is_tax = true;
                $wp_query->is_archive = true;
                $wp_query->is_home = false;

                // Make is_tax($taxonomy) work
                $wp_query->queried_object = $t;
                $wp_query->queried_object->taxonomy = $taxonomy;

                // If term is null, get_terms (query.php line 2043) will get all terms of this taxonomy
                $wp_query->set( 'term', null );
                break;
            }
        }
    }
}

OTHER TIPS

Though the above answer will work for the default setups in wordpress. If you are rewriting the slug names for your taxonomies then Jan Fabry's answer won't work. It just requires a modification.

Also I would suggest to no do this as this will not fit with other plugins that you are might be using which does not know that you are using an index page for your taxonomy. It will start spitting undefined notices and other errors.

add_action( 'init', 'wpse4663_init' );
function wpse4663_init()
{
    // The custom taxonomy rewrite rules end up at the top of the rewrite array
    register_taxonomy(
        'wpse4663',
        array( 'post' ),
        array(
            'label' => 'WPSE 4663',
        )
    );

    // So there probably is no danger in adding this specific rewrite rule there too
    // We re-use the existing `taxonomy` query var, but with no `term`
    // We clean this up in `parse_query`, otherwise get_posts() complains
    // You could make this work for all taxonomies (categories, tags, ...) by doing this repeatedly
    // But then it's probably better to do this in the `rewrite_rules_array` filter
    add_rewrite_rule( 'wpse4663(/page/([0-9]+))?/?$', 'index.php?taxonomy=wpse4663&paged=$matches[2]', 'top' );
}

add_filter( 'parse_query', 'wpse4663_parse_query' );
function wpse4663_parse_query( &$wp_query )
{
    // is_tax is only true if both a taxonomy and a term are set, otherwise is_home is true
    // But we don't want that: is_tax and is_archive should be true, is_home should be false
    if ( !$wp_query->is_tax && $taxonomy_query = $wp_query->get( 'taxonomy' ) )       {
        foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy => $t ) {
            if($t->rewrite && isset($t->rewrite['slug']){
                $slug = $t->rewrite['slug'];
            }
            else{
                $slug = $t->query_var;
            }

            if ( $t->query_var && $taxonomy_query == $slug ) {
                // Make sure the conditional tags work, so the right template is loaded
                $wp_query->is_tax = true;
                $wp_query->is_archive = true;
                $wp_query->is_home = false;

                // Make is_tax($taxonomy) work
                $wp_query->queried_object = $t;
                $wp_query->queried_object->taxonomy = $taxonomy;

                // If term is null, get_terms (query.php line 2043) will get all terms of this taxonomy
                $wp_query->set( 'term', null );
                break;
            }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top