Custom URIs in WordPress
I’m planning some changes for my website for the upcoming release of WordPress 2.1. Basically, I want to start using WordPress as a content management system instead of a plain old blogging tool, and the new version can handle that a bit better than the current one, 2.0.5. But I also want to do some tricky things with where different types fo contrent are stored, and that means delving into WordPress’s internals, including its mod_rewrite rules. It took a lot of trial and error, but I finally managed to get it working.
With the new setup, I’m planning on having only two main categories, A and B. Each has a couple of child categories; let’s call them A1, A2, B1, and B2. The site’s front page will be at the root, www.example.com/, and WP handles that just fine. However, it wants to put the page for category A at example.com/category/A, and nothing I did would fix this. I tried calling $wp_rewrite->category_base = '/'; but that gave me example.com//A, which is also no good. I ended up having to directly modify the WP code (which I hate having to do), changing rewrite.php to this (starting on line 370):
if ( empty($this->category_base) ) $this->category_structure = $this->front; else $this->category_structure = $this->category_base . '/';
Doing that fixes the URIs that WP generates, but it doesn’t fix the rewrite rules. In other words, clicking on a link to example.com/B/B1 gives a 404 error. Frustratingly and somewhat inexplicably (to me, anyway), example.com/B/B1 continued to work. This turns out to be pretty straightforward to adjust, but there’s a little more to the story first.
I want the URIs for category A and its two children to all be on the same level. In other words, the URIs should be example.com/A, example.com/A1, and example.com/A2. The first step in acheiving this is to adjust the links that WordPress generates. This is easy to do with a filter. I put the following code in the functions.php file for my theme:
function hide_subcategories($content) { $content = str_replace('/A/A1', '/A1', $content); $content = str_replace('/A/A2', '/A2', $content); return $content; } add_filter('the_permalink', 'hide_subcategories'); add_filter('the_category', 'hide_subcategories');
Strangely, these links all work right out of the box without having to mess with the rewrite rules. I don’t understand it at all.
Finally, I had to add some new rewrite rules. I’m pretty familiar with mod_rewrite, so it would have been easy for me just to add the rules directly. This approach seems like a hack, prove to breaking, and neither elegant nor good form. There is a function in WordPress 2.1 called add_rewrite_rule, which seems like it should work. I couldn’t get it to work. I ended up writing another filter:
function add_my_rewrites($rules) { $my_rules = array( 'B/B1' => 'index.php?cat=4' ); return ( $rules + $my_rules ); } add_filter('rewrite_rules_array', 'add_my_rewrites');
That solves the problem. Now I can add all the rules I need to properly redirect folks.
One of the biggest headaches in this was not being able to see all of WordPress’s internal rewrite rules. Here’s a snippet of code to spit them out on the top of ever page (so it should only be used for debugging purposes):
echo '<pre>'; print_r( $wp_rewrite->wp_rewrite_rules() ); echo '</pre>';
This was all done with WordPress 2.1 RC1, so maybe some of the weirdness will be fixed in the final version. At least I know that my site will be closer to what I want it to be.




Better WordPress Category URIs | P.C. Shannon on 28 February 2007 at 10:25 am | Permalink
[...] was going to write today about how I’ve improved on my previous solution for manipulating the category URIs in WordPress, but then I came across the Top Level Categories [...]