Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

This is a repost of an earlier question I had, but I like to go into more details now to be able to fully solve this.

So again, with (normal) posts changing the permalink is as easy as going to Settings > Permalink and by changing it to anything you like such as the broadly used %category%/%postname%.html. This all works. If only this was as easy for the custom post type and it's taxonomies as well.

So this is what I like to accomplish.

  1. http://mywordpress.com/portfolio.html - Display all posts in all categories.
  2. http://mywordpress.com/portfolio/music/ - Display all posts in this category.
  3. http://mywordpress.com/portfolio/music/trance/ - Display all posts in this (child) category.
  4. http://mywordpress.com/portfolio/music/trance/Tiesto.html - Display the post.

What I got so far is the following:

  1. First I created a custom_post_type named project and a taxonomy project_category.
  2. I created a page Portfolio and gave it a Page Template that will list all of the post_type = project posts. How can I add .html to the permalink of pages? It now links to http://mywordpress.com/portfolio while I want http://mywordpress.com/portfolio.html. This should solve the first issue.
  3. Then things will get tough, because we don't know by forehand how many subcategories there, maybe there are even none. So the structure we are after is portfolio/(CATEGORY PATH FROM TOP TO CHILD)/post.html. I am still stuck at this point. I think I should somehow get the last category added to the path and pass that along the project_category, which should lead to a taxonomy.php file where I can process it properly.
  4. I haven't tackled this neither but it should have something to do with %postname%.html at the end of something.

I hope my problem is clear and that there are brave developers which will help me tackle this problem which has already keep me busy for four FULL days!

share|improve this question
The solution I gave in the last question should have worked that way, if you implemented it correctly. The only thing is you can't get the html part –  Manny Fleurmond Sep 20 '11 at 14:43
Yes but it was locked to a specific path, so only category/subcategory/page while there might not be subcategories or even more. This is more dynamic. –  Mark Sep 20 '11 at 15:58
Or I did not implement it properly ;) –  Mark Sep 20 '11 at 15:59

2 Answers 2

Ok I think I might have a solution. I have no idea if this is the right way to accomplish this, but as for now it's the only thing that seems to work.

add_filter('rewrite_rules_array', 'mmp_rewrite_rules');

function mmp_rewrite_rules($rules) {
    $newRules                               = array();
    $newRules['portfolio/(.+)/(.+?).html$'] = 'index.php?project=$matches[2]';
    $newRules['portfolio/(.+)/?$']          = 'index.php?project_category=$matches[1]'; 

    return array_merge($newRules, $rules);

add_filter('request', 'mmp_rewrite_request');

function mmp_rewrite_request($vars) {
    if (isset($vars['project_category'])) {
        if (strpos($vars['project_category'], '/') !== false) {
            $categories = explode('/', $vars['project_category']);
            $vars['project_category'] = $categories[count($categories) - 1];

    return $vars;
share|improve this answer

Please, read 2 ADVICES:

for example, you want to have(like category) such permalink structure:

(unique or duplicate slug names doesnt matter in this case)

...... At first, you may need to set permalinks to /%category%/%postname%.


you can register a custom taxonomy new_cars for custom post types:

add_action( 'init', 'my_f32' ); function my_f32() {  $args = array(  # http://codex.wordpress.org/Function_Reference/register_taxonomy
        'public'=>true, 'show_ui'=>true,    //'show_in_nav_menus' => true,
        'show_admin_column'=>true, 'hierarchical'=>true,    'query_var'=>true,  'rewrite'=>array('with_front'=>true,'hierarchical'=>true),  
    register_taxonomy( 'new_cars', array(), $args );

add_action( 'init', 'myf_63' );function myf_63() { 
    $post_types = array('mercedes','ferarri','lambordjini');
    foreach ($post_types as $value)
        $args = array(  # http://codex.wordpress.org/Function_Reference/register_post_type
                'label'=>$value,     'labels' => array('name' => $value.' pagess' , 'singular_name' => $value.' page'),
                'public' => true,               //'exclude_from_search' => false,
                'publicly_queryable'=> true, 'show_ui'=>true,   //'show_in_nav_menus' => true,
                //'show_in_menu' => 'edit.php?post_type=page',//true,       //'menu_position' => 5,
                'capability_type' => 'post', 'hierarchical' => true,        'supports' => array( 'title', 'editor', 'thumbnail' ,'page-attributes'), 
                //'taxonomies' => array('category', 'new_cars'),
                'has_archive' => true,      //'permalink_epmask'=>EP_PERMALINK, 
                'rewrite' => array('with_front'=>true), 'query_var'=> true,     'can_export' => true,   
            register_post_type( $value, $args );


However, this wont change permalink structure, and you might have to add some other codes (like user MARK has answered)

to get the desired permalink HIERARCHICAL structure, then you'd better to register custom post type new_cars (INSTEAD OF taxonomy creation)!!
instead of
$post_types = array('mercedes','ferarri','lambordjini');
change to:
$post_types = array('new_cars');

then, at first, publish several normal custom post (i.e. with names MERCEDES, FERARRI..). ONLY AFTER that, while publishing another new post, choose parent (MERCEDES or etc)... enter image description here

So, your permalinks will be like :

p.s. if you will need search functionality for sub-levels, then use custom search query

share|improve this answer

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.