I found this link too much helpful. This is what I code so far and got it working for all scenarios except two scenarios.

register_post_type( 'article',
        'labels' => array(
            'name' => 'Article',
            'singular_name' => 'Article',
            'add_new' => 'Add Article',
            'add_new_item' => 'Add New Article',
            'edit' => 'Edit',
            'edit_item' => 'Edit Article',
            'new_item' => 'New Article',
            'view' => 'View',
            'view_item' => 'View Article',
            'search_items' => 'Search Article',
            'not_found' => 'No Article',
            'not_found_in_trash' => 'No Post found in Article',
            'parent' => 'Parent Article'

        '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%',
            'with_front' => true
        'has_archive' => 'articles',
        'register_meta_box_cb' => 'add_article_metaboxes'

    'hierarchical' => true,
    'labels' => $labels,
    'query_var' => true,
    'rewrite' => array('slug' => 'articles', 'hierarchical' => true),

add_filter('rewrite_rules_array', 'mmp_rewrite_rules');
function mmp_rewrite_rules($rules) {
    $newRules  = array();
    $newRules['articles/(.+)/(.+)/(.+)/?$'] = 'index.php?article=$matches[3]'; 
    $newRules['articles/(.+)/(.+)/?$'] = 'index.php?article=$matches[2]';
    $newRules['articles/(.+)/?$'] = 'index.php?article_category=$matches[1]'; 

    return array_merge($newRules, $rules);

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, '/', 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 = '/', $nicename = false, $visited = array()) {    
    $chain = '';   
    $parent = &get_term($id, $taxonomy);

    if (is_wp_error($parent)) {
        return $parent;

    if ($nicename)    
        $name = $parent -> slug;        
        $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;    

But this solution not working in two scenarios.

1st Scenario: On Child Taxonomy direct link
e.g: sitename.com/articles/parenttax/childtax/

2nd Scenario: On Pagination of Custom Post page
e.g: sitename.com/articles/parenttax/childtax/postname/page/2

Do I have to create separate function for them or just need to add new rules for it?

1 Answer 1


When you create permalink structures like /article/%category%/%postname%/, it becomes very complicated when %category% is hierarchical. The problem WordPress runs into is knowing if after the second slash, the next part of the URL is a category or a post. For instance, in the url /article/parent/child/, is "child" a subcategory of "parent", or is it a post named "child"? In your case, it's even worse because your articles are also hierarchical.

Your best bet is to add a predictable or static separator between the two. Here are some examples:


If you insist on maintaining the structure you propose, it's not impossible, but it would require some custom programming far beyond the scope of a Q & A site like this one.

  • Thanks a lot for your prompt response. Okay Matthew I got your point. But still one question is coming in mind that can we create two separate functions or rules. One rule/function if child category is last url segment and second rule/function if post name is last url segment. Apologies in advance, if question does not make sense.
    – Noman
    May 28, 2013 at 6:42
  • Yes, you could. See my answer here on intercepting the request object and altering it. It would still require a good deal of custom programming outside the scope of this site. Furthermore, that's going to create a great deal of issues with feeds, pagination, trackbacks, etc. If I were you, I'd definitely go with the separator in the URL. May 28, 2013 at 13:18
  • Okay Matthew I agreed with you and applied the separator and it worked very well for me. But It created another issue, actually I have one another taxonomy in my site which is 'gallery_category'. And all of its tax, child tax and custom post pages giving 404 error. In fact I have not applied any url rewriting on it.
    – Noman
    May 28, 2013 at 13:47
  • And neither defined rewrite in register_taxonomy and register_posttype. Still it is not working, I don't know why. Please help me in thi.
    – Noman
    May 28, 2013 at 13:48
  • That sounds like a separate issue, so you should open a separate question. May 28, 2013 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.