WP Rewrite Rules – Custom post type & taxonomy

You can achieve this without adding a rule for every term via the rewrite argument when you register your post type and taxonomy. The only extra rule you need is to handle pagination for the taxonomy.

First, register the post type. The order you register post type and taxonomy is important! I’ve left out most arguments to focus on the important bits:

$args = array(
    'has_archive' => 'custom-type',
    'rewrite' => array(
        'slug' => 'custom-type/%custom-tax%',
        'with_front' => false
    )
);
register_post_type( 'custom-type', $args );

Then register the taxonomy:

$args = array(
    'rewrite' => array(
        'slug' => 'custom-type',
        'with_front' => false
    )
);
register_taxonomy( 'custom-tax', array( 'custom-type' ), $args );

Then add the rewrite rule to handle taxonomy pagination:

function wpd_taxonomy_pagination_rewrites(){
    add_rewrite_rule(
        'custom-type/([^/]+)/page/([0-9]+)/?$',
        'index.php?custom-tax=$matches[1]&paged=$matches[2]',
        'top'
    );
}
add_action( 'init', 'wpd_taxonomy_pagination_rewrites' );

And to get the selected term in the permalink, filter post_type_link:

function wpd_post_link( $post_link, $id = 0 ){
    $post = get_post($id);  
    if ( is_object( $post ) && $post->post_type == 'custom-type' ){
        $terms = wp_get_object_terms( $post->ID, 'custom-tax' );
        if( $terms ){
            foreach( $terms as $term ){
                if( 0 == $term->parent ){
                    return str_replace( '%custom-tax%' , $term->slug , $post_link );
                }
            }
        } else {
            return str_replace( '%custom-tax%' , 'uncategorized', $post_link );
        }
    }
    return $post_link;
}
add_filter( 'post_type_link', 'wpd_post_link', 1, 3 );

Leave a Comment