Permalinks: custom post type -> custom taxonomy -> post

I am having trouble working with WordPress rewrite rules, and could use some help.

I have a custom post type called _shows_.

All shows have a single custom taxonomy category _show-category_. A _show_ will never have more than one _show-category_.

I would like my urls to route in this manner:

www.mysite.com/shows/  =>  archive-shows.php

www.mysite.com/shows/%category%/ => taxonomy-show-category.php

www.mysite.com/shows/%category%/%postname%/ => single-shows.php

So as a real world example, lets say we have a _show-category_ “Foo” and a _show_ post titled “Bar” that has “Foo” as it’s _show-category_. I would expect my WordPress app to look like this:

www.mysite.com/shows/foo/ => shows all posts under the foo category
www.mysite.com/shows/foo/bar => shows the indivual post

I try to avoid plugins when possible, but am open to any solution.

1

First, register your taxonomy and set the slug argument of rewrite to shows:

register_taxonomy(
    'show_category',
    'show',
    array(
        'rewrite' => array( 'slug' => 'shows', 'with_front' => false ),
        // your other args...
    )
);

Next, register your post type and set the slug to shows/%show_category%, and set has_archive argument to shows:

register_post_type(
    'show',
    array(
        'rewrite' => array( 'slug' => 'shows/%show_category%', 'with_front' => false ),
        'has_archive' => 'shows',
        // your other args...
    )
);

Last, add a filter to post_type_link to substitute the show category in individual show permalinks:

function wpa_show_permalinks( $post_link, $post ){
    if ( is_object( $post ) && $post->post_type == 'show' ){
        $terms = wp_get_object_terms( $post->ID, 'show_category' );
        if( $terms ){
            return str_replace( '%show_category%' , $terms[0]->slug , $post_link );
        }
    }
    return $post_link;
}
add_filter( 'post_type_link', 'wpa_show_permalinks', 1, 2 );

EDIT

Forgot the has_archive argument of register_post_type above, that should be set to shows.

Leave a Comment