I’ve spent a few days trying to learn how to best add rewrite rules. So far my understanding is that a suitable way to add simple rules is to use add_rewrite_rules()
, with large thanks to Jan Fabry on this exchange who’s elaborations have been of great use.
Although he mentions add_rewrite_tags()
I haven’t seen a guide on it explaining when it’s beneficial to use it, as opposed to other ways to add rewrite rules, or any good examples on its usage. It seems to be a more powerful tool, but that’s about all I can fathom. I find the examples in the Codex to be too cryptic or incomplete. Could someone elaborate on it or point to some resource? I found nothing useful on Google.
edit:
Its Codex page talks about ‘generally’ using it in conjunction with add_rewrite_rules()
, but doesn’t elaborate. Similarly the Codex page for add_rewrite_rules()
refers to add_rewrite_tags()
but it too is very sparse on information. When and how would such a combination be used? The only example I found is this answer by Rob Vermeer which I don’t understand.
The fundamental difference is:
- The
add_rewrite_rule()
adds a particular rule which is interpreted - The
add_rewrite_tag()
adds a placeholder to use in url structures. This placeholder is then used to generate multiple rules.
For instance – suppose you’re a travel agent advertising hotels in various countries. You may want a hotel’s url to be like
www.example.com/hotels/UK/Balmoral
Where the country (UK in this example) is a custom taxomony term and Balmoral is a hotel (post type). We could add rewrite rules for this, but then we would have to generate a rule for:
- the hotel itself
- the hotel’s attachments
- A rule for hotels (posts) where it spills over several pages etc.
Generating these rules can become complicated. Furthermore we’ll probably be competing with WordPress’s own rules for that post type – generated from the permastructure we set when registering the post type. (In any case, let WordPress do the work).
This ‘permastructure’ – similar to what you set for posts in the permalink settings – determines the rewrite rules WordPress generates. But since we want a structure which contains some unknown (the country) – which we want interpreted – we need to provide a placeholder of the form %country%
. (It’s almost identical to %category%
for posts).
For example:
add_action_init('init','wpse71305_register_types');
function wpse71305_register_types(){
//You'll need to register the country taxonomy here too.
//Add 'country' tag.
add_rewrite_tag('%country%', '([^&/]+)'));
//Register hotel post type with %country$ tag
$args = array(
...
'has_archive'=>true,
'rewrite' => array(
'slug'=>'hotels/%country%',
'with_front'=> false,
'feed'=> true,
'pages'=> true
)
...
);
register_post_type('hotel',$args);
}
Note: WordPress doesn’t know how to generate the url from the %country%
tag – you need to tell it do that. (I cover this in an article I’ve linked to below).
Finally WordPress will also store the matched value so you can retrieve it via get_query_var()
(something you don’t with a standard rewrite rule).
You can also create tags to be used in the permastructure of posts (set it in the Permalink settings page).
By adding a tag, we can use it in permastructures. WordPress then knows
- What to expect
- How to interpret the url (check it matches)
- How to interpret the value (i.e. ‘UK’)
(As reference see this article I wrote: http://wp.tutsplus.com/tutorials/creative-coding/the-rewrite-api-the-basics/).
Edit
As noted in the comments the above example is a poor as register_taxonomy()
in fact calls add_rewrite_tag()
.
Regarding the Codex documentation about using them ‘in combination’: this is perhaps misleading as they can both be used independently. As noted above, however, add_rewrite_tag()
adds the tag name to the WordPress-understand ‘query variables’. In practice this allows you to retrieve the value with get_query_var()
. Thus, when add_rewrite_rule()
is used with add_rewrite_tag()
, the variable will be stored by WordPress. But there are other ways of doing this (see this answer – note also Rob Vermeer’s comment).
Also related: How to retrieve $_GET variables from rewritten URLs?