Customizing WordPress Rewrite Rules

WordPress, with search engine friendly permalinks enabled, uses Apache mod_rewrite to redirect web page requests to index.php. From that point onwards WordPress uses its own internal rewrite rules to determine what content to display for a URL. In this post I take a look at how to customize WordPress’ internal rewrite rules.

WordPress stores the rewrite rules as an associative array. The array’s keys are regular expressions with the corresponding values being the rewrite. For example:

'categories/(.+?)/?$' => 'index.php?category_name=$matches[1]',

WordPress loops over the array and feeds each key to preg_match. The rewrite corresponding to the first regular expression that matches the requested URL will determine which database query is executed.

In the rewrite, $matches is an array populated by preg_match with the matching sub-sets with the first one starting at array index 1. The rewrites are basically WordPress public query variables. You can create your own query vars by using the add_rewrite_tag function.

The rewrite rules are cached in the WordPress database in the wp_options table with the option_name “rewrite_rules”. They are recreated every time you visit the admin settings > permalinks page. You can also force the recreation of the rewrite rules by calling the function flush_rewrite_rules().

Add Custom Rewrite Rules

Adding custom rewrite rules is as easy as hooking into the generate_rewrite_rules action:

add_action( 'generate_rewrite_rules', 'my_custom_rewrite_rules' );
function my_custom_rewrite_rules( $wp_rewrite ) {
    $my_rule = array( 'foo/([^/]+)/?$' => 'index.php?name=$matches[1]' );
    $wp_rewrite->rules = $my_rule + $wp_rewrite->rules;

Keep in mind that the rules are cached and have to be flushed. This is best done on plugin activation:

register_activation_hook( __FILE__, 'flush_rewrite_rules' );

Other functions that help customize rewrite rules are add_permastruct and add_rewrite_endpoint. These make it easier to add rules but hooking into generate_rewrite_rules gives you more fine grained control.

Leave a Reply

Your email address will not be published. Required fields are marked *