PureNews

PureNews is an amazingly sleek and powerful news theme with unlimited color variations.

View full feature list Check out the live demo Buy this theme today

Remove the Category Base from your Permalinks

Posted by on 1st Feb 2009 WordPress Coding & Design 9 comments

There’s one question that a lot of people have asked over time about using WordPress, but there’s not really a clear cut answer. How can you remove the Category Base from your WordPress permalinks? This may not be a major concern for a standard blog site, but it may be of use to some, and I think it’s definitely more use to those using WordPress as a CMS.

My method so far works for a permalink structure of /%category%/%post-name%/. Without any modifications, this will give a permalink link such as /category/post-category/post-name/. However, since at least WordPress 2.6, going to /post-category/post-name/ without the initial category ‘directory’ in place, has worked with this permalink structure. This is due to the internal working of WordPress.

Removing the category base isn’t part of WordPress as it’s not advised to be used. If you have a category called ‘news’ and a page called ‘news’, which one is to be displayed when you go to http://www.domain.com/news/ ? So I can understand the reasons behind it not being readily available to remove the category base, however if you’re in control of your own site and keep that in mind, then I don’t see any reason why you can’t remove the base.

So where do we start? Well first off you need to check your permalinks settings. This will only work (at present) if you have the structure mentioned above. So if you go to Settings -> Permalinks and ensure you have a custom permalink set up of

/%category%/%post-name%/

If you want to do this on a pre-existing site and that isn’t your structure then you would be best off not proceeding with this method as I wouldn’t advise changing your structure unless you have just a handful of pages. If you do change your structure then you need to also be creating a .htaccess redirect for each post!

What we then need to do is remove the base from the permalinks. We can do this in our functions.php theme file using the filter and function below:

[sourcecode language="php"]add_filter(‘user_trailingslashit’, ‘remcat_function’);
function remcat_function($link) {
return str_replace(“/category/”, “/”, $link);
}[/sourcecode]

This takes every permalink and removes the /category/ ‘directory’ from it. If you’ve changed your category base name then it’s unlikely you’ll be wanting to do this anyway, but if you do, then just change line 4 from /category/ to which ever base name you’ve used (surrounded by the forwardslashes of course).

Now, on the front end of your site, your category listings, blog posts and ‘filed under’ post meta data should contain links to the category or posts without the category directory within them. At this point, most of your site should continue to function as usual, minus the category base, and a lot of the methods I found were fine up to this point too, however a lot of people had trouble with viewing a category page and then trying to go to page 2 eg. /category-name/page/2/. It didn’t work.

So to fix this we need to make use of WordPress’s internal rewrite, and bit like mod rewrite, so that it keeps the correct URL in the address bar but loads the correct page too.

First of all we need to regenerate the rewrite rules already written using the flush_rules() function. We do this on initialisation of the page using the action and function below (again this goes in your functions.php theme file)

[sourcecode language="php"]add_action(‘init’, ‘remcat_flush_rules’);
function remcat_flush_rules() {
global $wp_rewrite;
$wp_rewrite->flush_rules();
}[/sourcecode]

Finally we need to tell WordPress which page to actually load if someone has gone to page X of a category. To do this we use the filter and function below.

[sourcecode language="php"]add_filter(‘generate_rewrite_rules’, ‘remcat_rewrite’);
function remcat_rewrite($wp_rewrite) {
$new_rules = array(‘(.+)/page/(.+)/?’ => ‘index.php?category_name=’.$wp_rewrite->preg_index(1).’&paged=’.$wp_rewrite->preg_index(2));
$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}[/sourcecode]

Here the important line is line 3:

$new_rules = array('(.+)/page/(.+)/?' => 'index.php?category_name='.$wp_rewrite->preg_index(1).'&paged='.$wp_rewrite->preg_index(2));

The array key dictates the pattern of the URL we want to be checked, and the array value specifies the URL to actually display. In this case we could have a URL of /news/page/3/ and then we’re saying to display the page index.php?category_name=news&paged=3 which is the true URL.

.htaccess Redirects

Finally, if this site is not a brand new site then you want to ensure that anyone going to the old url with the category base in is redirected through to the new version. We do this with a redirect rewrite, to match the URL containing the category base and then remove it and redirect the user to the new URL. You need to have mod rewrite enabled on your server for this and can use the following code

[sourcecode language="html"]RewriteRule ^category/(.+)$ /$1 [R=301,L][/sourcecode]

Place the above code after your RewriteEngine code, which should be present for Permalinks anyway ie.

[sourcecode language="html"]# BEGIN WordPress

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

RewriteRule ^category/(.+)$ /$1 [R=301,L][/sourcecode]

Again, if you have a base other than ‘category’ then you’ll have to change the last line above to reflect that. Also, if you’ve installed WordPress within a directory within the root eg. ‘wp’ or ‘news’, then you need to change the last line to

[sourcecode language="html"]RewriteRule ^wp/category/(.+)$ /wp/$1 [R=301,L][/sourcecode]

Which includes a directory of ‘wp’.

Conclusion

I wouldn’t recommend that you take this straight to a live site but test it on a test install first. Not because it doesn’t work, but there are a lot of instructions to follow! I hope to extend this to not be dependent on the permalink structure hopefully for next week.

A PHP Developer using WordPress to power both blogging and commercial CMS sites. I've written and released a couple of plugins for WordPress and am currently writing plugins for use on commercial websites.

9 comments - Leave a reply
  • Posted by Nicholas | Pixobyte. on 1st Feb 2009

    Thank you very much, when I removed the %Category% from the permalink, it didnt work properly so I had to use the permalink including Category too. Thanks this solved the problem I had while creating a CMS. :-)

  • Posted by The Moneyac on 2nd Feb 2009

    Wow thanks for the guide.

    I am always sacred of coding, I just have a "codephobia", too scared to ruin things. Thanks for the tip, gonna check it out and play with it.

    Cheers,

    The Moneyac

  • Posted by Alex Lim on 2nd Feb 2009

    I use only /%postname%/ in custom permalink. Is only show post name.

  • Posted by Sarah on 4th Feb 2009

    Cheers for the comments all. Alex – that's fine however I think the category name will add to a bit of understanding about what the user is viewing, and potentially aid in SEO, but each to their own :)

  • Posted by Sean on 7th Feb 2009

    Out of curiosity, is there a way to go in the opposite direction a bit easier, so that you can add the category_base into permalinks?

    For example, I'm using the /%category%/%postname%/ permalink structure. My categories I changed to 'topics' using the optional category base in the WP admin panel, and I would like all permalinks to show up as:

    http://www.site.com/topics/category/the-post-slug
    or
    http://www.site.com/topics/category/sub-category/…

    I'm know everyone is frustrated with and concerned about removing the categories portion of links, but perhaps it's easier to work with it and head in the other direction? I've found several workarounds, but all seem incredibly complex. While I love WordPress, I wish they would eliminate the default "category" because it makes for poor content management.

    I think if you have to change code in more than one file to implement a basic link structure change, the software is bloated and not efficient…but that's just me. Any ideas?

    Great post by the way!

  • Posted by Sarah on 8th Feb 2009

    Hi Sean. I'm assuming at present your links include 'topics' instead of 'categories' then. You should be able to take the code posted above and rather than have it remove 'topics/' actually make it change to 'topics/category/'. Then in your htaccess you'll just need to alter the 301 to detect any link with 'topics/' in but not 'category/' and make it redirect to 'topics/category/'. Off the top of my head something like

    <code>RedirectMatch ^topics/[^category/](.*)$ /topics/category/$1</code>

    If that doesn't make sense let me know and I'll redo the code for you :)

  • Posted by Sean on 8th Feb 2009

    Sarah, that's great to know. Thank you! It makes perfect sense as I look at the rewrite rule. I'm not a programmer, but comfortable enough hacking code here and there to understand the process of what it's doing. Rewrite rules are an area I am slowly improving in, the more I work with WP.

    Thanks again, and have a wonderful week!

  • Posted by McNallen on 5th Feb 2011

    I found that simply adding ./ to "category base" deletes the directory from the URL… THAT SIMPLE…

  • Posted by Gianfranco on 14th Mar 2011

    Hi Sarah, I'd like to know your thoughts about this permalinks issue: http://wordpress.org/support/topic/permalinks-inf…

    Thanks!