Custom taxonomy on permalink

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:

/%city%/%category%/%postname%/

So this is what I like to accomplish.

Read More
  • 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');
    flush_rewrite_rules();
}
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;
    endif;
}
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),  

Related posts

Leave a Reply

1 comment

  1. 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.