The title is pretty vast and non-descriptive, but it sets the general idea of the post. In general the Permalinks system that WordPress uses is pretty flexible, but it also has it’s limitations. Quite recently as I was working on a client’s project, I stumbled upon one of them.
The project was to create a Frequently Asked Questions database, using WordPress. The client wanted the following structure for the database(this is a simplified version)::
- Index of the database (
http://example.com/faq/
) [Index of the whole database]- Main Category (
http://example.com/faq/category/
) [Index of the Main Category]- Post in the Main Category (
http://example.com/faq/category/post-1-slug/
) [View only Post 1] - Sub-Category (
http://example.com/faq/category/sub-category/
) [Index of the Sub-Category]- Post in the Sub-Category (
http://example.com/faq/category/sub-category/post-2-slug/
) [View only Post 2]
- Post in the Sub-Category (
- Post in the Main Category (
- Another Main Category ( http://example.com/faq/another-category/ ) [Index of the other Main Category=]
- Main Category (
Everything looks normal(as structure of the URL’s) for the regular user, but WordPress has a different idea on the matter Instead of an URL like http://example.com/faq/category/
we will be able to see the index of the Main Category at an URL like http://example.com/faq-category/category/
, which as you can notice is quite different from the initial idea. To fix this issue we have to add a couple of custom Rewrite Rules and functions.
The first step is to register the new Custom Post Type and it’s Custom Taxonomy. Here’s how:
This code registers the new post type and it’s “FAQ Categories” taxonomy, which we will use to categorize the questions.
After we register the new post type, we have to add two functions that will make the Permalinks work the way we want them to:
In the code above we registered two functions – register_faq_rewrite_rules()
and fix_faq_subcategory_query()
.
The first function adds the following rewrite rules:
faq/([^/]+)/?$
– this rule will be applied when the URL of the page that is being loaded looks something like “faq/any-character/” – in other words when the URL starts(after the part with the home page URL) with “faq/” followed by any combination of symbols, without “/”( “([^/]+)” ), and possibly followed by a “/”( “/?” ). Also in order to match, this part has to be the last part of the URL(in other words there won’t be a match, if the URL is “faq/any-character/something”).When the current URL matches, the page will display a FAQ Category archive for the category(according to the example I gave) “any-character”.faq/([^/]+)/([^/]+)/?$
– this rule is almost the same as the previous, except for the URL that would match this rule looks like “faq/any-character/post-slug/”.This will display a post with slug “post-slug” from a FAQ Category with slug “any-character” OR an FAQ archive for a FAQ category with a slug “post-slug” that is child of the “any-character” FAQ category.faq/([^/]+)/([^/]+)/page/(\d{1,})/?$
– this rule will match paginated results for a sub-category archive.faq/([^/]+)/([^/]+)/([^/]+)/?$
– this rule is almost the same as the previous, except for the URL that would match this rule looks like “faq/any-character/sub-category/post-slug/”.This will display a post with slug “post-slug” from a FAQ Category with slug “sub-category”.
The second function on the other hand fixes the issue with the sub-categories. The issue itself consists in the fact, that when you try to load a page with URL faq/category/child-category/
, WordPress would try to load a post with slug “child-category” instead of the sub-category with slug “child-category”. The function itself is probably not the best solution to the problem, at least because we have to make an additional query to the database, but it’s the only solution I was able to come-up with Since the function checks if there are posts with slug “child-category”, if you happen to have posts(from the FAQ post type) and categories with the same slug, you might get unexpected results
That’s enough to make the FAQ database run properly, but right now if you want to fully use the new Rewrite rules, you’d have to write every URL manually(I mean, when you link to content from the FAQ database). This is because WordPress doesn’t know how to generate the links, so that they match our idea. That’s why we add a couple of more functions:
The above functions “filter” the output from two built-in WordPress functions, which take care of creating the correct URL’s for all pages, posts, taxonomy archives, etc.
There is one more issue, that could be a serious problem for some users – the duplicate content issue. There is a rather large chance, that Google or another search engine that crawls your website to get quite upset by the fact that it can find identical content in two different URL’s(for instance faq-item/post-2-slug/
and faq/category/sub-category/post-2-slug/
). This can be avoided with a function that redirects the users to the correct address, but I’ll leave this up to you
If you want to see the whole thing in action, you can go to Custom Permalinks Test.