flexible rewrite ‘ramble’ URLs with WordPress

I want to access my post with id 17 like this:

http://localhost/archives/17/moot-bla-foo-ramble

Read More

In other words, the id shall decide, everything thereafter may (or may not) be the slug or anything else. Much like these links leading to the same page (many other sites do the same):

I tried to define a rewrite-rule like this near the top of my .htaccess:

RewriteRule ^archives/(d{1,12})(?:/.*) archives/$1 [NC]

This almost works, i.e. goes to the right page, but get’s me a page-not-found then,
because wordpress looks at PATH_INFO again (I think) and states $query_string now is string attachment=moot-bla-foo-ramble

I do not want to do a 301 redirect.

My favourite or course, if such thing existed in Permalink Settings:Custom Structure

/archives/%post_id%/%wildcard%

Albeit that would make the ‘ramble’ mandatory, so even better…

/archives/%post_id%(/%wildcard%)?

wishful thinking, I guess.

Related posts

Leave a Reply

3 comments

  1. You shouldn’t use the htaccess instead you should use the WordPress APIs

    e.g.

    function custom_rewrite( $wp_rewrite ) {
    
        $feed_rules = array(
            'archives/(d+)(?:/.*)+'    =>  'index.php?p='. $wp_rewrite->preg_index(1)
    );
    
        // ( array merge must be done this way, to ensure new rule comes first )
        $wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
    }
    // refresh/flush permalinks in the dashboard if this is changed in any way
    add_filter( 'generate_rewrite_rules', 'custom_rewrite' );
    
  2. Essentially the same as @Tom’s answer, but using the provided add_rewrite_rule wrapper:

    add_action('init','wpse48481_rewrite_rules');
    function wpse48481_rewrite_rules(){
        add_rewrite_rule('^archives/([0-9]{1,})/','index.php?p=$matches[1]','top');
    }
    

    This will check for urls of the form:

     http://www.yoursite.com/archives/99/something-else
    

    and interpret it as the post/page/cpt with ID =99. Of course the regex can be whatever you like…

  3. I am sorry to say, but all this brought me into kneep-deep troubles. Suddenly tag and category urls ceased to work, giving a “Well this is embarrassing” empty search page…

    Even a neutral, non-changing callback triggered by flush w/o adding anyrules would break things like
    * /archives/tag/kiwis
    * /archives/categories/fruits

    Removing it all and saving /wp-admin/options-permalink.php (i.e. numeric settings) fixes it again. Repeatedly. Very verified. Also see this thread at wordpress.org.

    Basically, spending a day, I have come up with a very simple hack, that appears to work.
    adding this in the .htacces, before the wordpress block

    RewriteRule ^archives/(d{1,12})(?:/.*) archives/$1 [NC,L]
    

    adding this in my theme’s functions.php. Directly. No hook.

    if ( isset($_SERVER["REDIRECT_URL"]) )
        $_SERVER["REQUEST_URI"] = $_SERVER["REDIRECT_URL"];
    

    Yep, pretty dirty, writing to a $_SERVER variable.
    And voila, all my testcases work ( simple url, ramble-attached url, tags, category, …)
    (nb: without the if your very start page ceases to work (never-ending redirect loop)