Wordpress - Add category base to url in custom post type/taxonomy

Change your rewrite to add the course query var:

'rewrite' => array('slug' => 'courses/%course%')

Then filter post_type_link to insert the selected course into the permalink:

function wpa_course_post_link( $post_link, $id = 0 ){
    $post = get_post($id);  
    if ( is_object( $post ) ){
        $terms = wp_get_object_terms( $post->ID, 'course' );
        if( $terms ){
            return str_replace( '%course%' , $terms[0]->slug , $post_link );
        }
    }
    return $post_link;  
}
add_filter( 'post_type_link', 'wpa_course_post_link', 1, 3 );

There are also plugins like Custom Post Type Permalinks that can do this for you.


The solution for me had three parts. In my case the post type is called trainings.

  1. Add 'rewrite' => array('slug' => 'trainings/%cat%') to the register_post_type function.
  2. Change the slug to have a dynamic category.
  3. "Listen" to the new dynamic URL and load the appropriate template.

So here is how to change the permalink dynamically for a given post type. Add to functions.php:

function vx_soon_training_post_link( $post_link, $id = 0 ) {
    $post = get_post( $id );
    if ( is_object( $post ) ) {
        $terms = wp_get_object_terms( $post->ID, 'training_cat' );
        if ( $terms ) {
            return str_replace( '%cat%', $terms[0]->slug, $post_link );
        }
    }

    return $post_link;
}

add_filter( 'post_type_link', 'vx_soon_training_post_link', 1, 3 );

...and this is how to load the appropriate template on the new dynamic URL. Add to functions.php:

function archive_rewrite_rules() {
    add_rewrite_rule(
        '^training/(.*)/(.*)/?$',
        'index.php?post_type=trainings&name=$matches[2]',
        'top'
    );
    //flush_rewrite_rules(); // use only once
}

add_action( 'init', 'archive_rewrite_rules' );

Thats it! Remember to refresh the permalinks by saving the permalinks again in de backend. Or use the flush_rewrite_rules() function.


Got the solution!

To have hierarchical permalinks for custom post type install Custom Post Type Permalinks(https://wordpress.org/plugins/custom-post-type-permalinks/) plugin.

Update registered post type. I have post type name as help center

function help_centre_post_type(){
    register_post_type('helpcentre', array( 
        'labels'            =>  array(
            'name'          =>      __('Help Center'),
            'singular_name' =>      __('Help Center'),
            'all_items'     =>      __('View Posts'),
            'add_new'       =>      __('New Post'),
            'add_new_item'  =>      __('New Help Center'),
            'edit_item'     =>      __('Edit Help Center'),
            'view_item'     =>      __('View Help Center'),
            'search_items'  =>      __('Search Help Center'),
            'no_found'      =>      __('No Help Center Post Found'),
            'not_found_in_trash' => __('No Help Center Post in Trash')
                                ),
        'public'            =>  true,
        'publicly_queryable'=>  true,
        'show_ui'           =>  true, 
        'query_var'         =>  true,
        'show_in_nav_menus' =>  false,
        'capability_type'   =>  'page',
        'hierarchical'      =>  true,
        'rewrite'=> [
            'slug' => 'help-center',
            "with_front" => false
        ],
        "cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",
        'menu_position'     =>  21,
        'supports'          =>  array('title','editor', 'thumbnail'),
        'has_archive'       =>  true
    ));
    flush_rewrite_rules();
}
add_action('init', 'help_centre_post_type');

And here is registered taxonomy

function themes_taxonomy() {  
    register_taxonomy(  
        'help_centre_category',  
        'helpcentre',        
        array(
            'label' => __( 'Categories' ),
            'rewrite'=> [
                'slug' => 'help-center',
                "with_front" => false
            ],
            "cptp_permalink_structure" => "/%help_centre_category%/",
            'hierarchical'               => true,
            'public'                     => true,
            'show_ui'                    => true,
            'show_admin_column'          => true,
            'show_in_nav_menus'          => true,
            'query_var' => true
        ) 
    );  
}  
add_action( 'init', 'themes_taxonomy');

This is line makes your permalink work

"cptp_permalink_structure" => "/%help_centre_category%/%post_id%-%postname%/",

you can remove %post_id% and can keep /%help_centre_category%/%postname%/"

Don't forget to flush permalinks from dashboard.