Custom permalink structure: /%custom-post-type%/%custom-taxonomy%/%post-name%/ Custom permalink structure: /%custom-post-type%/%custom-taxonomy%/%post-name%/ wordpress wordpress

Custom permalink structure: /%custom-post-type%/%custom-taxonomy%/%post-name%/


Lucky for you, I just had to do this for a client project. I used this answer on the WordPress Stackexchange as a guide:

/** * Tell WordPress how to interpret our project URL structure * * @param array $rules Existing rewrite rules * @return array */function so23698827_add_rewrite_rules( $rules ) {  $new = array();  $new['projects/([^/]+)/(.+)/?$'] = 'index.php?cpt_project=$matches[2]';  $new['projects/(.+)/?$'] = 'index.php?cpt_project_category=$matches[1]';  return array_merge( $new, $rules ); // Ensure our rules come first}add_filter( 'rewrite_rules_array', 'so23698827_add_rewrite_rules' );/** * Handle the '%project_category%' URL placeholder * * @param str $link The link to the post * @param WP_Post object $post The post object * @return str */function so23698827_filter_post_type_link( $link, $post ) {  if ( $post->post_type == 'cpt_project' ) {    if ( $cats = get_the_terms( $post->ID, 'cpt_project_category' ) ) {      $link = str_replace( '%project_category%', current( $cats )->slug, $link );    }  }  return $link;}add_filter( 'post_type_link', 'so23698827_filter_post_type_link', 10, 2 );

When registering the custom post type and taxonomy, be sure to use the following settings:

// Used for registering cpt_project custom post type$post_type_args = array(  'rewrite' => array(    'slug' => 'projects/%project_category%',    'with_front' => true  ));// Some of the args being passed to register_taxonomy() for 'cpt_project_category'$taxonomy_args = array(  'rewrite' => array(    'slug' => 'projects',    'with_front' => true  ));

Of course, be sure to flush rewrite rules when you're done. Good luck!


Since WordPress changed a lot in the recent years there is a new solution for this.

// Used for registering cpt_project custom post type$post_type_args = array(  'rewrite' => array(    'slug' => '/%custom-post-type%/%custom-taxonomy%/%postname%/',    'with_front' => true    'walk_dirs' => false  ));

%custom-post-type% must match the name for your custom post type%custom-taxonomy% must match the name for your taxonomythat WordPress automatically creates the right rewrite rules and links

with 'walk_dirs' => false you prevent WP from creating crazy rules like with only [^/]+/ cause your link starts with a custom-post-type

and often this dir walk isn't even needed cause u access only the sites in your structure or separate taxonomy sites.

With this your rewrite rules are as precise as possible, and you don't need to fetch the rules with

add_filter( 'rewrite_rules_array', 'so23698827_add_rewrite_rules' );

and prepend them later on with

add_filter( 'post_type_link', 'so23698827_filter_post_type_link', 10, 2 );

as mentioned in the accepted answer. This saves memory and execution time!

Hope this helps anyone, who is searching for this Problem with WP Versions > 5.X