I have created hierarchy based custom permalinks with the help of this link, but now it is causing a 404 error on another custom taxonomy used in the site. I want custom permalinks on this other taxonomy also, but if I don’t use any rewrite arguments and leave it on its default permalink, it is still not working.
My code for the second taxonomy:
register_post_type(
'gallery',
array(
'public' => true,
'menu_position' => 15,
'supports' => array( 'title', 'editor', 'comments', 'thumbnail' ),
'taxonomies' => array( '' ),
'menu_icon' => get_template_directory_uri() . '/img/icon_gallery.png',
'register_meta_box_cb' => 'add_gallery_metaboxes'
)
);
register_taxonomy(
'gallery_category',
'gallery',
array(
'hierarchical' => true,
'labels' => $labels
)
);
And here is my first custom taxonomy code:
register_post_type(
'article',
array(
'public' => true,
'hierarchical' => true,
'menu_position' => 15,
'supports' => array( 'title', 'editor', 'comments', 'thumbnail' ),
'taxonomies' => array( '' ),
'menu_icon' => get_template_directory_uri() . '/img/icon_article.png',
'query_var' => true,
'rewrite' => array(
'slug' => '%article_category%/articles',
'with_front' => true
),
'has_archive' => '%article_category%',
'register_meta_box_cb' => 'add_article_metaboxes'
)
);
register_taxonomy(
'article_category',
'article',
array(
'hierarchical' => true,
'labels' => $labels,
'query_var' => true,
'rewrite' => array( 'slug' => '', 'hierarchical' => true ),
)
);
Function for custom permalink:
function filter_post_type_link( $link, $post ) {
if ( $post->post_type != 'article' )
return $link;
if ( $cats = get_the_terms( $post->ID, 'article_category' ) ) {
$link = str_replace( '%article_category%', get_taxonomy_parents( array_pop( $cats )->term_id,
'article_category', false, "https://wordpress.stackexchange.com/", true ), $link ); // See custom function defined below
}
return $link;
}
add_filter( 'post_type_link', 'filter_post_type_link', 10, 2 );
After many efforts I have solved it, but it’s not completely what I want, as I had to compromise on one thing and passed some separators in the URL. Example:
example.com/separator1/parentatx/childtax/separator2/postname/
In order to avoid 404 errors, in case of pagination and another custom taxonomy, I created some rewrite rules. Here is my code:
First post type and custom taxonomy registration code:
register_post_type(
'article',
array(
'public' => true,
'hierarchical' => true,
'menu_position' => 15,
'supports' => array( 'title', 'editor', 'comments', 'thumbnail' ),
'taxonomies' => array( '' ),
'menu_icon' => get_template_directory_uri().'/img/icon_article.png',
'query_var' => true
'rewrite' => array(
'slug' => 'articles/%article_category%/topic/',
'with_front' => true
),
'has_archive' => '/all-articles/',
'register_meta_box_cb' => 'add_article_metaboxes'
)
);
register_taxonomy(
'article_category',
'article',
array(
'hierarchical' => true,
'labels' => $labels,
'query_var' => true,
'rewrite' => array( 'slug' => '/articles/', 'hierarchical' => true ),
)
);
In the first custom taxonomy, I used ‘articles’ and ‘topic’ as separators; you can use any according to your scenario.
Second post type and custom taxonomy registration code:
register_post_type(
'gallery',
array(
'public' => true,
'menu_position' => 15,
'supports' => array( 'title', 'editor', 'comments', 'thumbnail' ),
'taxonomies' => array( '' ),
'menu_icon' => get_template_directory_uri().'/img/icon_gallery.png',
'query_var' => true,
'rewrite' => array(
'slug' => 'galleries/%gallery_category%/images/',
'with_front' => true
),
'has_archive' => '/all-galleries/',
'register_meta_box_cb' => 'add_gallery_metaboxes'
)
);
In the second custom taxonomy, I used ‘galleries’ and ‘images’ as separators; you can use any according to your scenario.
The function for rewrite rules:
add_filter( 'rewrite_rules_array', 'mmp_rewrite_rules' );
function mmp_rewrite_rules( $rules ) {
$newRules = array();
//Rules for First Taxonomy
$newRules['articles/(.+)/(.+)/(topic)/(.+)/?$'] = 'index.php?article=$matches[4]';
$newRules['articles/(.+)/(topic)/(.+)/?$'] = 'index.php?article_category=$matches[1]&article=$matches[3]';
$newRules['articles/(.+)/(.+)/?([0-9]{1,})/?$'] = 'index.php?article_category=$matches[1]&page=$matches[3]';
$newRules['articles/(.+)/(.+)/(page)/?([0-9]{1,})/?$'] = 'index.php?article_category=$matches[1]&page=$matches[4]';
$newRules['articles/(.+)/?$'] = 'index.php?article_category=$matches[1]';
//Rules for Second Taxonomy
$newRules['galleries/(.+)/(.+)/(images)/(.+)/?$'] = 'index.php?gallery=$matches[4]';
$newRules['galleries/(.+)/(images)/(.+)/?$'] = 'index.php?gallery_category=$matches[1]&gallery=$matches[3]';
$newRules['galleries/(.+)/(.+)/?([0-9]{1,})/?$'] = 'index.php?gallery_category=$matches[1]&page=$matches[3]';
$newRules['galleries/(.+)/(.+)/(page)/?([0-9]{1,})/?$'] = 'index.php?gallery_category=$matches[1]&page=$matches[4]';
$newRules['galleries/(.+)/?$'] = 'index.php?gallery_category=$matches[1]';
return array_merge( $newRules, $rules );
}
The functions to change the custom post type URL according to custom taxonomy hierarchy:
function filter_post_type_link( $link, $post ) {
if ( $post->post_type != 'article' && $post->post_type != 'gallery' )
return $link;
if ( $post->post_type == 'article' ) {
if ( $cats = get_the_terms( $post->ID, 'article_category' ) ) {
$link = str_replace( '%article_category%', get_taxonomy_parents( array_pop( $cats )->term_id,
'article_category', false, "https://wordpress.stackexchange.com/", true ), $link ); // See custom function defined below
}
return $link;
} elseif ( $post->post_type == 'gallery' ) {
if ( $cats = get_the_terms( $post->ID, 'gallery_category' ) ) {
$link = str_replace('%gallery_category%', get_taxonomy_parents( array_pop( $cats )->term_id,
'gallery_category', false, "https://wordpress.stackexchange.com/", true ), $link); // See custom function defined below
}
return $link;
}
}
add_filter( 'post_type_link', 'filter_post_type_link', 10, 2 );
// My own function to do what get_category_parents does for other taxonomies
function get_taxonomy_parents( $id, $taxonomy, $link = false, $separator="https://wordpress.stackexchange.com/", $nicename = false, $visited = array() ) {
$chain = '';
$parent = &get_term( $id, $taxonomy );
if ( is_wp_error( $parent ) ) {
return $parent;
}
if ( $nicename )
$name = $parent -> slug;
else
$name = $parent -> name;
if ( $parent -> parent && ( $parent -> parent != $parent -> term_id ) && !in_array( $parent -> parent, $visited ) ) {
$visited[] = $parent -> parent;
$chain .= get_taxonomy_parents( $parent -> parent, $taxonomy, $link, $separator, $nicename, $visited );
}
if ( $link ) {
// Nothing, can't get this working :(
} else {
$chain .= $name . $separator;
}
return $chain;
}