How to enable hierarchical permalinks for hierarchical taxonomies

If you have a category called “term” and a subcategory called “subterm”, your can access subterm posts at /cat/subcat. But this doesn’t work out of the box with custom taxonomies. They are accessible at /taxonomy/subterm, but not /taxonomy/term/subterm.

They’ve gone over this in the WordPress Trac (, and it kind of looks like they have a solution, but as I’ve never used the Trac and don’t fully understand its language (diffs, etc), I need someone more experienced to actually tell me how to implement this. Is there code there that I have to paste into WordPress core files? Is this already implemented and I can add something to my theme’s functions.php?

If possible I’d prefer not to modify any core files. Help!

Solutions Collecting From Web of "How to enable hierarchical permalinks for hierarchical taxonomies"

This is implemented in WordPress now as of 3.1.

When you register your taxonomy, make sure to set rewrite hierarchical to true as well as the taxonomy itself:

register_taxonomy('genre',array('book'), array(
'hierarchical' => true, // this makes it hierarchical in the UI
'labels' => $labels,
'show_ui' => true,
'query_var' => true,
'rewrite' => array( 'hierarchical' => true ), // this makes hierarchical URLs

Is there a way to add a parameter to an already-registered custom taxonomy? All of my taxonomies were built with a plugin, so it would be nice if I could add something to functions.php that would just add ‘rewrite’ => array( ‘hierarchical’ => true ) to those taxonomies.

You should be able to use register_taxonomy to re-register the taxonomy you want to affect.

WARNING: Untested code!
(Just off the top of my head, mostly. I take no responsibility for broken sites.):

function reregister_taxonomy() {
    # the post types that the taxonomy is registered to
    $post_types = array('post');
    # set this to the taxonomy name
    $tax_name = 'TAXONOMY_NAME_TO_CHANGE';
    # load the already created taxonomy as array so we can
    # pass it back in as $args to register_taxonomy
    $tax = (array)get_taxonomy($tax_name);

    if ($tax) {
        # adjust the hierarchical necessities
        $tax['hierarchical'] = true;
        $tax['rewrite']['hierarchical'] = true;

        # adjust the hierarchical niceties (these could be ignored)
        $tax['labels']['parent_item'] = sprintf(__("Parent %s"),
        $tax['labels']['parent_item_colon'] = sprintf(__("Parent %s:"),

        # cast caps to array as expected by register_taxonomy
        $tax['capabilities'] = (array)$tax['cap'];
        # cast labels to array
        $tax['labels'] = (array)$tax['labels'];
        # register the taxonomy with our new settings
        register_taxonomy($tax_name, array('post'), $tax);
# init action with a late priority so other taxonomies are loaded
# alternatively could be done with the `registered_taxonomy` action hook
add_action('init', 'reregister_taxonomy', 9999);

Only after writing this did I realize this question was a year-and-a-half old, mayhaps somebody will find it useful anyhow.

To make hierarchical permalinks working you need to add rewrite rules. I’ve managed to assemble some code making a custom post type with a custom taxonomy working with parent/child terms reflected in permalinks. It’s not perfect, but it’s working!

function keha_add_rewrite_rules() {
        add_rewrite_rule( '^posttype_slug/(.+?)/(.+?)/(.+?)$', 'index.php?taxonomy=$matches[1]&taxonomy=$matches[2]&posttype=$matches[3]', 'top' );
        add_rewrite_rule( '^posttype_slug/(.+?)/(.+?)/$', 'index.php?posttype=$matches[2]', 'top' );
        add_rewrite_rule( '^posttype_slug/(.+?)/(.+?)/(.+?)$', 'index.php?posttype=$matches[3]', 'top' );
        add_rewrite_rule( '^posttype_slug/(.+?)/(.+?)/?$', 'index.php?taxonomy=$matches[2]', 'top' );
        add_rewrite_rule( '^posttype_slug/(.+?)$', 'index.php?taxonomy=$matches[1]', 'top' );
add_action('init', 'keha_add_rewrite_rules');

View my working example at Github:

Thanks to @anubhava

A little study about WP Rewrite API find out the solution.

1) I have created a custom rewrite url and placed it into my functions.php

function services_rewrite_basic() {
  add_rewrite_rule('^services/.*', 'index.php?page_id=110&level=$matches[1]&level=$matches[1]&level=$matches[1]', 'top');
add_action('init', 'services_rewrite_basic');

2) And finally just saved permlink page without any changes and it bloody does the trick.