Custom Slug for a custom post type and default post

You’ll have to add your own rewrite rules to make this work, no way around that.

First, don’t use the %category% rewrite tag, register your own tag and use that for the CPT categories:

function wpd_query_vars( $qvars ) {
    $qvars[] = 'cptcat';
    return $qvars;
}
add_filter( 'query_vars', 'wpd_query_vars' );

You can then swap that tag for the category in post_type_link. Note that this only handles one level of term. If you want to do parent/child term permalinks, you’ll have to modify this function and add a rewrite rule to catch every level of term hierarchy.

function wpd_test_post_link( $post_link, $id = 0 ){
    $post = get_post($id);  
    if ( is_object( $post ) && $post->post_type == 'your_cpt' ){
        $terms = wp_get_object_terms( $post->ID, 'category' );
        if( $terms ){
            foreach( $terms as $term ){
                if( 0 == $term->parent ){
                    return str_replace ( '%cptcat%' , $term->slug , $post_link );
                }
            }
        } else {
            return str_replace ( '%cptcat%' , 'uncategorized', $post_link );
        }
    }
    return $post_link;
}
add_filter( 'post_type_link', 'wpd_test_post_link', 1, 2 );

Now this still won’t work because WordPress thinks your permalink is a parent/child category request. Add a rewrite rule to override that:

function wpd_test_rewrites(){
    add_rewrite_rule(
        '([^/]+)/CPT/([^/]+)/?$',
        'index.php?your_cpt=$matches[2]',
        'top'
    );
}
add_action( 'init', 'wpd_test_rewrites' );

Leave a Comment