WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I created 1 custom post type (projects) with 2 taxonomies (clients / fields) to filter the results (like categories).

At the end, it should be like this where project_name is the same custom post displayed in single-projects.php :

  • my-site/projects/
  • my-site/projects/project_name
  • my-site/projects/fields/
  • my-site/projects/fields/project_name
  • my-site/projects/clients/
  • my-site/projects/clients/project_name

Like this, based on the re-written url, i'll be able to easily display the current term selected and navigate post per post (in single-projects.php) within this specific term .

I'm using an archive to display all custom posts: archive-projects.php.

The custom posts permalinks are like this: my-site/projects/project_name

I've got a taxonomy template to display custom posts related to a term and it's working well: taxonomy.php

So far so good.

But permalinks are still like this : my-site/projects/project_name.

And i'd like to give them a different permalink based on the current taxonomy and get a different URL as written above.

I already found this and it's working well in a standard case (a blog with few categories for example), but i got stuck when i'm trying to adapt to taxonomies. I can create the new url but can't give it to the permalink post.

Any help or advice? thanks

[UPDATE] Here is what i managed to do so far :

function multiple_taxonomy_post_link($CPT_url = ){
// check permalink structure for the required construct; /%category%/%postname%/
if (strrpos(get_option('permalink_structure'), '%category%/%postname%') !== false){
// get the current post
global $post, $wp_query;

// prepare variables for use below
$post_id = $term_id = 0;
$new_CPT_url = ''; 

// for taxonomies
if (is_tax())
  // remember current category and post
  $term_obj = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
  $term_id = $term_obj->term_id;
  $post_id = $post->ID;

  // add the post slug to the current url
  $new_CPT_url = $_SERVER['REQUEST_URI'] . $post->post_name;

else if (is_singular('projects'))
  $term_object = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );

  // remember current category and post
  $post_id = $wp_query->post->ID;
  if ($term_object) $term_id = $term_object->term_id;

  // replace the slug of the post being viewed by the slug of $post
  $new_CPT_url = $_SERVER['REQUEST_URI'].$post->post_name;

if ($post_id > 0 && $term_id > 0 && !empty($new_CPT_url))
    $current_tax = get_query_var( 'taxonomy' );
    $terms = get_the_terms( $post->ID, $current_tax );
  // make sure categories match!
  foreach($terms as $term)
    if ($term->term_id == $term_id)
      $CPT_url = $new_CPT_url;
// always return an url!
return $CPT_url;
add_filter('post_type_link', 'multiple_taxonomy_post_link');

it displays well the new permalinks on taxonomy template and redirections are pointing to the desired post but WP keeps writing the single post url as my-site/projects/project_name. Is it because the targeted post is a custom post type ?

share|improve this question

I'm about to release a plugin to do just that (and some other things). You'll have to modify your rewrite rules. This code works for category posts. Perhaps, if you work on it a little bit it will get you the same behavior for post types and taxonomies.

First, generate the rules you need:

function get_category_rules() {
    $rules = array();

    * Will generate patterns for:
    *  (category)/
    *  category/(subcategory)
    *  category/subcategory/(post)
    *  feed/(category)
    *  feed/category/(subcategory)

    $feed_sufix = '/feed/?(rss|rss2|atom)?/?$';
    $page_sufix = '/page/?([0-9]{1,})?/?$';

    /* Walk within the categories by level */

    $categories = get_categories(array(
        'orderby'    => 'slug',
        'hide_empty' => false,
        'exclude'    => implode(',', $excludes)
    foreach($categories as $category) {

        $level = 0;
        $path = '(' . $category->slug . ')';

        while (($category = get_category($category->parent)) && isset($category->term_id)) {
            $path = $category->slug . '/' . $path;

        // Feeds
        $rules[$level][$path . $feed_sufix] = 'index.php?category_name=$matches[1]&feed=atom';

        // Category archives
        $rules[$level][$path . '/?$'] = 'index.php?category_name=$matches[1]';

        // Category archive pages
        $rules[$level][$path . $page_sufix] = 'index.php?category_name=$matches[1]&paged=$matches[2]';

        // Posts
        $rules[$level][$path . '/([^/]+)/?$'] = 'index.php?name=$matches[2]';


    $retval = array();
    for ($i = count($rules) - 1; $i >= 0; $i--) {
        $retval = array_merge($retval, $rules[$i]);
    return $retval;

Then, merge these rules with the existing ones:

add_action('rewrite_rules_array', 'rewrite_rules');
function rewrite_rules($rules) {
    $category_rules = get_category_rules();
    $rules = array_merge($category_rules, $rules);
    return $rules;

And make *_permalink functions work with it.

add_filter('post_link', 'custom_post_permalink');
function custom_post_permalink ($post_link) {
    global $post;

    $cats = array_reverse(get_the_category($post->ID));
    if (!isset($cats[0]))
        return $post_link;

    $category = $cats[0];
    $path = $category->slug;

    while (($category = get_category($category->parent)) && isset($category->term_id)) {
        $path = $category->slug . '/' . $path;

    return str_replace(home_url(), home_url() . '/' . $path, $post_link);
share|improve this answer
Thanks a lot answering. I'll take a look and keep you informed. – HFord Aug 10 '12 at 13:22
First I'll try to make it work with categories. Just to be sure : shall i disable wp no category plugin, for this? Cause for a same post with 2 categories i got the same url : my_site/category2/category1/post_name – HFord Aug 10 '12 at 13:52
[UPDATE] wp no category plugin disabling does not change anything... – HFord Aug 10 '12 at 13:53
i get confused with the way rewriting and redirecting are done in WP. My issue right now could be simply sum-up as : How to keep the new URL on the adress bar and not be automatically replaced. – HFord Aug 10 '12 at 15:18

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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