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.

I need to access a page which is name 2011. The trouble is that WP thinks that I am trying to read the 2011 posts of my blog.

The only way I can make it work for the moment, is to change the permalink of my 2011 page to be mypage-2011.

Is there anyway I can make/force WP to use 2011 as permalink for the page 2011, so it can be viewed via www.site.com/2011

thx s

share|improve this question

1 Answer 1

up vote 4 down vote accepted

First of all rewrite handling can become very complicated very quickly - particularly when your desired structure conflicts with WordPress' default behaviour. The best advice is probably to just avoid such conflicts rather than try to resolve them. With that as a premable...

WordPress generates rewrite rules from various sources: from registered post types, rules that plug-ins manually add and also 'tags' (default / plug-in added). Tags are the %year%, %author% etc that you can use in your custom permalink structure. It also has rewrite rules that it automatically generates: These include date structures (see source). e.g.

  www.example.com/2012 => www.example.com?year=2012
  www.example.com/2012/05 => www.example.com?year=2012&monthnum=05

These rules are more specific than page rules, since they only apply to (in regex) ([0-9]{4}) - that is 4 digit numbers like 2012. (The second rule only applies to ([0-9]{4})/([0-9]{2}) e.g. 2012/05.

There are two solutions to this:

  • Change the rule for the %year% tag
  • Change the date rewrite rules

Change rule for the %year% tag

As mentioned above, the %year% tag expects a 4-digit number - and the corresponding rule only appears when this is met. You can change this rule so it only matches date/([0-9]{4}) - that is, it matches date/[four-digit-number]. To do that:

add_action('init','wpse56448_change_year_tag');
function wpse56448_change_year_tag(){
     add_rewrite_tag('%date%','(date/[0-9]{4})');
}

Warning: This means whenever the %year% tag is used (say in your custom permalink structure) - the year in the permalink must be preceded by date/. Notable changes include

  www.example.com/2012/05

no longer points to May 2012 archives. Instead you must use:

  www.example.com/date/2012/05

(similarly for the date archive).

For this reason, you might prefer to use method 2.


Change the date rewrite rules

When the date rewrite rules are being generated they are filtered (see source) using the date_rewrite_rules filters.

More specifically an array of the form regex=>query is filtered. An array where the key is a regular expression, and the value is how it is interpreted as a query). E.g.:

Array
(
    [([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&feed=$matches[4]
    [([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/(feed|rdf|rss|rss2|atom)/?$] => index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&feed=$matches[4]
    [([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/page/?([0-9]{1,})/?$] => index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&paged=$matches[4]
    [([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$] => index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]
    [([0-9]{4})/([0-9]{1,2})/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?year=$matches[1]&monthnum=$matches[2]&feed=$matches[3]
    [([0-9]{4})/([0-9]{1,2})/(feed|rdf|rss|rss2|atom)/?$] => index.php?year=$matches[1]&monthnum=$matches[2]&feed=$matches[3]
    [([0-9]{4})/([0-9]{1,2})/page/?([0-9]{1,})/?$] => index.php?year=$matches[1]&monthnum=$matches[2]&paged=$matches[3]
    [([0-9]{4})/([0-9]{1,2})/?$] => index.php?year=$matches[1]&monthnum=$matches[2]
    [([0-9]{4})/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?year=$matches[1]&feed=$matches[2]
    [([0-9]{4})/(feed|rdf|rss|rss2|atom)/?$] => index.php?year=$matches[1]&feed=$matches[2]
    [([0-9]{4})/page/?([0-9]{1,})/?$] => index.php?year=$matches[1]&paged=$matches[2]
    [([0-9]{4})/?$] => index.php?year=$matches[1]
)

It's this last rule that is causing the problem. So you can remove it, and then add a replacement (if desired):

add_filter('date_rewrite_rules','wpse56448_date_rewrite_rules');
function wpse56448_date_rewrite_rules( $rules ){
    //Remove year rewrite rule:
    unset($rules['([0-9]{4})/?$']);

    //Replace it with something else
    $rules['year/([0-9]{4})/?$'] = 'index.php?year=$matches[1]';
    return $rules;
}

Now

  www.example.com/2012

goes to your page. And

  www.example.com/year/2012

points to the year archives. While the month archives remain unchanged. e.g.:

  www.example.com/date/2012/05

still points to May 2012 archive.

Warning: Clearly you can see another conflict arising if your 2012 page has a sub-page called '05'. Similar problems will occur if you use 'page', 'feed', 'atom' etc (see rewrite rules above). This method would require you to manually remove/replace each of the rules that need altering. This can get messy quickly - which is why its best just to avoid using these as page names.


Summary

First of all: any changes won't take effect until you flush the rewrite rules. Do this (only) by going to Settings > Permalinks and clicking save.

Method 2 is probably preferable - given that method 1 may do 'too much'. However, method 2 is a bit 'dirtier' - you're 'fine tuning' the date permastructure and you may find that you need to tune it further.

For instance, using method 2, if your 2012 page had a sub-page 05 - it's permalink would be be interpreted as the May 2012 archive. You would then need to alter the rewrite-rules for month archives. Going three-levels deep, with a page called '01' you will get the 1st May 2012 archive. At each level you also have problems if you have pages called 'page', or 'feed' and such. As mentioned, its probably best to try and avoid such names.

share|improve this answer
    
Thx Stephen, works –  salocin Jun 25 '12 at 13:37
    
this patch is affecting wordpress main source code. It should give trouble when updating.. right ? –  Frederic Bazin Jul 19 at 2:44
    
I'm not suggesting that you alter the source code, but instead you should create a plug-in for this code. That way, after an update, your changes will not be lost. It's possible that when WordPress updates the patch is either no longer needed or is incompatible. This is unlikely, but is why you need to test code you are using after an update. In this case, there is a trac ticket, but at the time of writing no patch. –  Stephen Harris Jul 19 at 11:54

Your Answer

 
discard

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.