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.

Okay so my question is quite simple. I need to implement some custom routing rules for my plugin. Those routes would only take one argument (so nothing complicated) and would look like : http://www.example.org/myroute/myargument

And ideally, this would call a custom class, and display a custom template (that could directly access the class).

What's the best approach for this ? Cheers

share|improve this question

1 Answer 1

up vote 3 down vote accepted

You need to do 3 important things.

  1. Create a custom rewrite rule to turn parts of the uri into values passed to index.php
  2. Add myroute and myargument as query vars to wordpress knows they are valid $_GET paramters when the rewrite rules pass something to them
  3. Flush the rewrite rules.

First, Im going to recommend that instead of http://www.example.org/myroute/myargument, you settle on some kind of special prefix or suffix to denote when the uri should be considered one of these special 'routes'. For the the sake of this example, I've chosen the prefix api, so that it would be http://www.example.org/api/myroute/myargument. I chose api because when i did something restful like what you seem to be working on, it was for an API.

The Code

add_filter( 'rewrite_rules_array','my_insert_rewrite_rules' );
add_filter( 'query_vars','my_insert_query_vars' );
add_action( 'wp_loaded','my_flush_rules' );

// flush_rules() if our rules are not yet included
function my_flush_rules(){
    $rules = get_option( 'rewrite_rules' );

    if ( ! isset( $rules['api/(.*?)/(.+?)'] ) ) {
        global $wp_rewrite;
        $wp_rewrite->flush_rules();
    }
}

// Adding a new rule
function my_insert_rewrite_rules( $rules )
{
    $newrules = array();
    $newrules['api/(.*?)/(.+?)'] = 'index.php?myroute=$matches[1]&myargument=$matches[2]';
    return $newrules + $rules;
}

// Adding the id var so that WP recognizes it
function my_insert_query_vars( $vars )
{
    array_push($vars, 'myroute', 'myargument');
    return $vars;
}

Quick Breakdown

Its all fairly straight forward, the regex pattern is added to a list of all the rewrite rules in WordPress, and your custom pattern is at the of the list. When the there is a match to the pattern, WordPress will stop looking, and pass the captured values to the back references in the index.php string.

Adding the query vars just makes them myroute and myargument valid for index.php to handle.

Alternative way of 'namespacing' your custom route

If you wanted to avoid using /api/ as a prefix, you could use a query string var instead. To do something like that you would change the regex to something like (.*?)/(.+?)\\?api=1 and then add api as an additional parameter to the array_push function in my_insert_query_vars().

That would change the custom route to be triggered anytime there is http://example.com/anytext/anytext?json=1.

Ignore the use of the term 'namespacing' - just used it for brevity.

If you dont 'namespace' with either a prefix or a suffix, you will end up with colliding uri patterns. This is because WordPress will have no way to distinguish your custom pattern from one intended to be a post or page. How would wordpress know if that 'myroute' is not a taxonomy, or a term, or a parent page?

Hope this helps.

share|improve this answer
    
Handy note: rules defined in my_insert_rewrite_rules follow order of definition! Start with the longest rule first then work down to the simplest, otherwise /api/myroute will override /api/myroute/myargument. –  npc Feb 25 at 17:42
1  
@npc Thats an important point to be aware of when creating custom rewrite rules, they can collide that way too. In the example above though, thats not a problem because /api/myroute would simply not be a valid path. –  eddiemoya Mar 3 at 19:37
    
great info, thanks. –  npc Mar 3 at 23:03
    
How could someone load a custom template from their plugin directory whenever the example.org/api/myroute/myargument page was requested? –  Matt Keys 2 days ago

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.