I have a long time problem and look forward for your help. I have a custom taxonomy of "city" (it is no hierarchical like tags). I just would like my URLs to look like this:


So this is what I like to accomplish.

  • http://example.com/city/moscow - Display all posts in taxonomy city-Moscow.
  • http://example.com/category/shopping - Display all posts in this category and all cities.
  • http://example.com/category/shopping/supermarket - Display all posts in this category and all cities.
  • http://example.com/moscow/shopping/ -Display all posts in this category in Moscow.
  • http://example.com/moscow/shopping/supermarket/ - Display all posts in this -child-category in Moscow.
  • http://example.com/moscow/shopping/supermarket/postname - Display the post.

I’ve made the following:

  1. I’ve created a custom taxonomy - city at first.
  2. I’ve added the code in function.php
function add_custom_taxonomies_city() {
    register_taxonomy('city', 'post', array(
        'hierarchical' => false,
        'labels' => array(
            'name' => _x( 'City', 'taxonomy general name' ),
            'search_items' =>  __( 'Search cities' ),
            'all_items' => __( 'All cities' ),
            'parent_item' => __( 'Parent Categories' ),
            'parent_item_colon' => __( 'Parent Categories:' ),
            'edit_item' => __( 'Edit city' ), 
            'update_item' => __( 'Update city' ),
            'add_new_item' => __( 'Add city' ),
            'new_item_name' => __( 'New city' ),
            'menu_name' => __( 'cities' ),

    'rewrite' => array(
        'slug' => 'city',
        'with_front' => false,
        'hierarchical' => false
add_action( 'init', 'add_custom_taxonomies_city', 0 ); 

add_filter('post_link', 'town_permalink', 10, 3);
add_filter('post_type_link', 'town_permalink', 10, 3);

function town_permalink($permalink, $post_id, $leavename) {
    if (strpos($permalink, '%city%') === FALSE) return $permalink;

// Get post
    $post = get_post($post_id);
    if (!$post) return $permalink;

// Get taxonomy terms
    $terms = wp_get_object_terms($post->ID, 'city');  
    if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
    else $taxonomy_slug = 'not-city';

    return str_replace('%city%', $taxonomy_slug, $permalink);

The result:

  • http://example.com/city/moscow - It works
  • http://example.com/category/shopping - It works
  • http://example.com/category/shopping/supermarket/ - It works
  • http://example.com/moscow/shopping/ - It works
  • http://example.com/moscow/shopping/supermarket/ - It doesn’t!!!!!
  • http://example.com/moscow/shopping/supermarket/postname – It doesn’t!!!!!

This post has a following link: http: //mysite.ru/ moscow/shopping/postname

But I need the links to contain the child-category.

  1. I’ve tried to solve the task with another option: I’ve added the following code into function. php
function addRoutes() {
    add_rewrite_tag('%city%', '(.+?)');
    add_rewrite_rule('(.+?)/(.+?)/([^/]+)(/[0-9]+)?/?$', 'index.php?city=$matches[1]&category_name=$matches[2]&name=$matches[3]&page=$matches[4]', 'top');
  add_rewrite_rule('(.?.+?)(/[0-9]+)?/?$', 'index.php?pagename=$matches[1]&page=$matches[2]', 'top');
add_action('init', 'addRoutes');

As a result

http://example.com/city/moscow - Page not found 404 error. http://example.com/category/shopping - Page not found 404 error.. http://example.com/category/shopping/supermarket/ - Page not found 404 error.. http://example.com/moscow/shopping/supermarket/postname –400 error

It seems the sustem doesn’t understand %city% What is wrong? Look forward for your help Can anybody help me? Thank you very much!

I decided to change the structure of the URLs to:

  • example.com/city/moscow/category/shopping/ -Display all posts in this category in Moscow.
  • example.com/city/moscow/category/shopping/supermarket/ - Display all posts in this -child-category in Moscow.
  • example.com/city/moscow/category/shopping/supermarket/postname - Display the post.

The code:

//The rewrite rules
function eg_add_query_vars( $query_vars ) {
    $new_vars = array( 'town' );

    return array_merge( $new_vars, $query_vars );
add_filter( 'query_vars', 'eg_add_query_vars' );

function eg_add_rewrite_rules() {
    global $wp_rewrite;

    $new_rules = array(
        'city/(.+?)/category/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=' . $wp_rewrite->preg_index(2),
'city/(.+?)/category/(.+?)/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=' . $wp_rewrite->preg_index(2) . '&category_name='. $wp_rewrite->preg_index(3),

//'city/(.+?)/category/(.+?)/(.+?)/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=' . $wp_rewrite->preg_index(2) . '&category_name='. $wp_rewrite->preg_index(3). '&page='. $wp_rewrite->preg_index(4),// This is me effort to write the rule for posts (doesn't work)   
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
add_action( 'generate_rewrite_rules', 'eg_add_rewrite_rules' );

//creating the permalink:
function city_permalink($permalink, $post_id, $leavename) {
    if (strpos($permalink, '%city%') === FALSE) return $permalink;

        // Get post
        $post = get_post($post_id);
        if (!$post) return $permalink;

        // Get taxonomy terms
        $terms = wp_get_object_terms($post->ID, 'town');  
        if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
        else $taxonomy_slug = 'not-city';

    return str_replace('%town%', $taxonomy_slug, $permalink);}

    function wp_town_query( $query ) {
    if( isset( $query->query_vars['city'] ) ):
        if( $city = get_term_by( 'id', $query->query_vars['city'], 'city' ) )
            $query->query_vars['town'] = $city->slug;
add_action( 'parse_query', 'wp_city_query' );

My settings in Permalink admin page: city/%city%/category/%category%/%postname%/

as a result I have: - example.com/city/moscow/category/shopping/ -works - example.com/city/moscow/category/shopping/supermarket/ - works but still I can't understand how to write the rule for posts: - example.com/city/moscow/category/shopping/supermarket/postname - doesn't. Pagination not working too.

I'll be glad to have any advice!

It's work:

'city/(.+?)/category/(.+?)/(.+?)/([^/]+)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=' . $wp_rewrite->preg_index(2). '&category_name=' . $wp_rewrite->preg_index(3). '&name=' . $wp_rewrite->preg_index(4), 
'city/(.+?)/category/(.+?)/page/?([0-9]{1,})/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=' . $wp_rewrite->preg_index(2). '&paged=' . $wp_rewrite->preg_index(3),
'city/(.+?)/category/(.+?)/?$' => 'index.php?city=' . $wp_rewrite->preg_index(1) . '&category_name=' . $wp_rewrite->preg_index(2),  

bumped to the homepage by Community yesterday

This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.

  • 1
    Please use the "edit" link and reformat your question. Hint: If you don't want to use your real domain, please use example.com that runs for exact that purpose. Thank you. – kaiser Feb 20 '13 at 14:00
  • Strongly recommend using 'get_the_terms' instead of 'wp_get_object_terms' as 'get_the_terms' will cache the result. Using 'wp_get_object_terms' will result in that query running every time the 'post_link' filter runs, which is like 10 times on the Edit Post screen. Ref core.trac.wordpress.org/browser/tags/3.9.1/src/wp-includes/… – TomHarrigan May 23 '14 at 20:28

Ok, so I will get negative points for this, but it should solve your problem, please dont be mad at me. Before anyone downvote me for this, I must say that I have nothing to do with the developers of this plugin:

For custom taxonomies and custom post types I often use a plugin named "Types". you can find it in install plugins at wordpress menu and should do the trick for you without any coding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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