0

I am checking the document for add_rewrite_rule at https://developer.wordpress.org/reference/functions/add_rewrite_rule/, based on its description, it said "Any value in the $after parameter that isn’t ‘bottom’ will result in the rule being placed at the top of the rewrite rules."

If I understand correctly, the following code:

  add_rewrite_rule('/rule1/', 'index.php?rule1', 'top');
  add_rewrite_rule('/rule2/', 'index.php?rule2', 'top');
  add_rewrite_rule('/rule3/', 'index.php?rule3', 'top');

will cause the rule priority of:

rule3(most high)
rule2(second high)
rule1

Is that correct?

1 Answer 1

1

Is that correct?

It's correct that rules with a $after value of top (or anything other than bottom) will be placed above all other rules (that have been registered by the time your code runs).

However, the rules would actually be in the same order add_rewrite_rule() is called, so as for the ones in question, you would see them in the following order in the generated rewrite rules (that are saved in the database, although could also be written to the .htaccess file), hence rule1 has the highest priority:

/rule1/
/rule2/
/rule3/

And that's because "top" and "bottom" rules (which are both extra/custom rules) are grouped and merged using array_merge() like so: (see WP_Rewrite::add_rule() on Trac)

if ( 'bottom' === $after ) {
    $this->extra_rules = array_merge( $this->extra_rules, array( $regex => $query ) );
} else {
    $this->extra_rules_top = array_merge( $this->extra_rules_top, array( $regex => $query ) );
}

PS: add_rewrite_rule() calls WP_Rewrite::add_rule().

Example 1

  • PHP:

    add_action( 'init', function () {
        add_rewrite_rule( '^rule1/?$', 'index.php?pagename=foo&bar=rule1', 'top' );
        add_rewrite_rule( '^rule2/?$', 'index.php?pagename=foo&bar=rule2', 'top' );
        add_rewrite_rule( '^rule3/?$', 'index.php?pagename=foo&bar=rule3', 'top' );
    } );
    
    add_action( 'init', function () {
        add_rewrite_rule( '^rule1b/?$', 'index.php?pagename=foo&bar=rule1b', 'bottom' );
        add_rewrite_rule( '^rule2b/?$', 'index.php?pagename=foo&bar=rule2b', 'bottom' );
    } );
    
  • A var_dump() of the generated/saved rules:

    array(101) {
      ["^wp-json/?$"]=>
      string(22) "index.php?rest_route=/"
      ... other core REST API rules.
      ["^wp-sitemap\.xml$"]=>
      string(23) "index.php?sitemap=index"
      ... other core sitemaps rules.
      ["^rule1/?$"]=>
      string(32) "index.php?pagename=foo&bar=rule1"
      ["^rule2/?$"]=>
      string(32) "index.php?pagename=foo&bar=rule2"
      ["^rule3/?$"]=>
      string(32) "index.php?pagename=foo&bar=rule3"
      ... category, tag, etc. rules.
      ["(.?.+?)(?:/([0-9]+))?/?$"]=>
      string(29) "index.php?pagename=$1&page=$2"
      ["^rule1b/?$"]=>
      string(33) "index.php?pagename=foo&bar=rule1b"
      ["^rule2b/?$"]=>
      string(33) "index.php?pagename=foo&bar=rule2b"
    }
    

Example 2

  • PHP:

    add_action( 'init', function () {
        add_rewrite_rule( '^rule1/?$', 'index.php?pagename=foo&bar=rule1', 'bottom' );
        add_rewrite_rule( '^rule2/?$', 'index.php?pagename=foo&bar=rule2', 'bottom' );
        add_rewrite_rule( '^rule3/?$', 'index.php?pagename=foo&bar=rule3', 'bottom' );
    } );
    
    add_action( 'init', function () {
        add_rewrite_rule( '^rule1b/?$', 'index.php?pagename=foo&bar=rule1b', 'top' );
        add_rewrite_rule( '^rule2b/?$', 'index.php?pagename=foo&bar=rule2b', 'top' );
    } );
    
  • A var_dump() of the generated/saved rules:

    array(101) {
      ["^wp-json/?$"]=>
      string(22) "index.php?rest_route=/"
      ... other core REST API rules.
      ["^wp-sitemap\.xml$"]=>
      string(23) "index.php?sitemap=index"
      ... other core sitemaps rules.
      ["^rule1b/?$"]=>
      string(33) "index.php?pagename=foo&bar=rule1b"
      ["^rule2b/?$"]=>
      string(33) "index.php?pagename=foo&bar=rule2b"
      ... category, tag, etc. rules.
      ["(.?.+?)(?:/([0-9]+))?/?$"]=>
      string(29) "index.php?pagename=$1&page=$2"
      ["^rule1/?$"]=>
      string(32) "index.php?pagename=foo&bar=rule1"
      ["^rule2/?$"]=>
      string(32) "index.php?pagename=foo&bar=rule2"
      ["^rule3/?$"]=>
      string(32) "index.php?pagename=foo&bar=rule3"
    }
    

So as you could see, in both examples, rule1 is always before rule2 and rule3, and rule1b is also always before rule2b.

1
  • 1
    Thank you very much!
    – alancc
    Oct 12, 2021 at 1:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.