With introduction of custom post types, additional templates WordPress loads and maybe custom rewrite rules websites can use, it can be a bit confusing what happens when WP loads and resolves the URL. Sometimes you will end up on wrong page, and here is to find out why.

Intro

If you don’t use permalinks structure for URL’s, you can skip this article. All this matters only when permalinks structure is on. And since most websites use them, it is useful to know how the pretty URL is resolved. When URL is parsed by WordPress, a long list of rewrite rules is used to match the URL (using regular expressions) to a query that WordPress can than understand and use to load and display data. If two rules are conflicted, the one with higher priority is used. If no rule is matched, WordPress will load 404 page. If the rule is matched, but the query returns no results, again 404 page will be displayed, this means that URL request was invalid.

If you have complex data structure with many post types, if you use even custom rewrite rules, you can end up with the 404 pages very often, if the rewrite rules are not resolved properly. In most cases, every URL request will resolve as a page if all other rewrite rules fail.

Get the list of all rewrite rules

You can always display list of all rewrite rules registered in WordPress. There is a simple function that can display all the rules in the table form:

function dev4press_debug_rewrite_rules() {
  global $wp_rewrite;
  echo '<div>';
  if (!empty($wp_rewrite->rules)) {
    echo '<h5>Rewrite Rules</h5>';
    echo '<table><thead><tr>';
    echo '<td>Rule</td><td>Rewrite</td>';
    echo '</tr></thead><tbody>';
    foreach ($wp_rewrite->rules as $name => $value) {
      echo '<tr><td>'.$name.'</td><td>'.$value.'</td></tr>';
    }
    echo '</tbody></table>';
  } else {
    echo 'No rules defined.';
  }
  echo '</div>';
}

Add the function to your code, and call it inside any theme template to print the list of all rewrite rules. Order of rules are also the priority, top rules are with highest priority. Reading the list can be confusing if you don’t understand how the URL rewrite in WordPress works, and it is more useful to developers for debugging.

Display resolved rewrite rule and loaded template

Now, we can use another function to show us how WordPress resolved the URL request and why the template is loaded:

function dev4press_debug_page_request() {
  global $wp, $template;
  define("D4P_EOL", "rn");

  echo '<!-- Request: ';
  echo empty($wp->request) ? "None" : esc_html($wp->request);
  echo ' -->'.D4P_EOL;
  echo '<!-- Matched Rewrite Rule: ';
  echo empty($wp->matched_rule) ? None : esc_html($wp->matched_rule);
  echo ' -->'.D4P_EOL;
  echo '<!-- Matched Rewrite Query: ';
  echo empty($wp->matched_query) ? "None" : esc_html($wp->matched_query);
  echo ' -->'.D4P_EOL;
  echo '<!-- Loaded Template: ';
  echo basename($template);
  echo ' -->'.D4P_EOL;
}
Debug Rewrite Rules in header

Debug Rewrite Rules in header

Best way to use this is to add the function into your code (functions.php in the theme), and to call it in the theme header.php template, best to do it on top, right after HEAD tag. Look at the image on the right for the example.

When you do that, whenever you load new page in the browser, the debug info about rewrite rule matched will be embedded as a comment on top of the header. And if you end up on 404 page, you can see why, what happened to resolved rule to do that.

Images bellow shows example output for this debug info. Request is always displayed without the domain name. First example is success matching of a request to a post, and loading of single.php template. First line is request, second line matched rule (regular expression), and when the rule is matched, request is transformed to a query (line 3). This query is something WordPress can interpret and load via proper template. Based on the query, WordPress creates a query object that is used to get the data and determine template to load (last line).

Matching Hello World single post

Matching Hello World single post

Next image is a custom rewrite rule for my GD Products Center plugin archive page that mixes both custom post type and taxonomy.

Matching archive for custom rewrite rule

Matching archive for custom rewrite rule 

Third example is for the URL that can’t be resolved properly. When all rules in WP fail, last one remaining is a single page rule. And this example has triggered that, and practically the whole request is matched as name for the page. And since such page doesn’t exists in the system, 404 template is loaded.

Matching ended up as a page that don't exits giving 404

Matching ended up as a page that don’t exits giving 404

If you use Dev4Press plugins this is already built-in some

If you use GD Press Tools Pro, you have a debugger module built-in that can display all the data we discussed here and more. If you use GD Custom Posts and Taxonomies Tools Pro (these functions: gdtt_debug_page_request_comment, gdtt_debug_rewrite_rules, gdtt_debug_page_request) or GD Products Center (these functions:  gdpc_debug_page_request_comment, gdpc_debug_rewrite_rules, gdpc_debug_page_request), so check the documentation for more details. And it will be added to xScape framework soon, and it will be easy to turn on or off.

Conclusion

So, now you can easily find out why WordPress loaded a page for every of the URL requests and find out likely cause to end up on the 404 page. This is also important when working with custom rewrite rules that can be in conflict and can cause 404 page to load.

2 Responses to “Debug WordPress rewrite rules matching”

  1. Marlon | April 26, 2012 at 6:47 pm

    Awesome tips! Love it! It will help me understand how rewrite works. Thanks for sharing.

  2. Stuart | June 26, 2012 at 7:22 pm

    Big props! I’ve wanted to get my head around clean url rewrites. This article and accompanying debug functions really sorted it for me. I’m working on a site with events and need to be able to list past/future events. I did it by registering a new query_var and passing it into a rewrite rule.
    Nice!

Leave a Reply

Dev4Press Plugins Pack

Dev4Press Plugins Pack

Personal$99.00
Business$249.00
Developer$499.00
GD bbPress Toolbox

GD bbPress Toolbox

Personal$39.00
Business$99.00
Developer$199.00
GD Custom Posts And Taxonomies Tools

GD Custom Posts And Taxonomies Tools

Personal$39.00
Business$99.00
Developer$199.00
GD Press Tools

GD Press Tools

Personal$39.00
Business$99.00
Developer$199.00
GD Products Center

GD Products Center

Personal$39.00
Business$99.00
Developer$199.00
xScape Theme Club

xScape Theme Club

Standard$149.00