add_rewrite_rule with bottom priority doesn’t handle the WordPress pages

When you point a rule to anything other than index.php, it gets interpreted as external and written to the .htaccess file. After external rules are parsed, requests get directed to WordPress, which parses the internal rules in php. This is the internal version:

function custom_rewrite() {
  add_rewrite_rule(
    '^(bar|baz|foo-.*)',
    'index.php?my_var=$matches[1]',
    'top'
  );
}
add_action( 'init', 'custom_rewrite' );

You’ll also need to register the custom query var you use in the rule. Note that page is already in use by WordPress

function wpd_query_vars( $qvars ) {
  $qvars[] = 'my_var';
  return $qvars;
}
add_filter( 'query_vars', 'wpd_query_vars' , 10, 1 );

This alone won’t do much, you’ll have to check if a page that matches your rule exists, and load your file if it doesn’t. We can do that on the parse_request action.

function wpd_parse_request( $request ) {
    // if the rule was matched, the query var will be set
    if( isset( $request->query_vars['my_var'] ) ){
        // check if a page exists, reset query vars to load that page if it does
        if( get_page_by_path( $request->query_vars['my_var'] ) ){
            $request->query_vars['pagename'] = $request->query_vars['my_var'];
            unset( $request->query_vars['my_var'] );
        // else load the file
        } else {
            include 'test.php';
            die();
        }
    }
    return $request;
}
add_action( 'parse_request', 'wpd_parse_request' );

Leave a Comment