add_rewrite_rule()
Adds a rewrite rule that transforms a URL structure to a set of query vars.
Any value in the $after parameter that isn't 'bottom' will result in the rule being placed at the top of the rewrite rules.
No Hooks.
Return
null
. Ничего (null).
Usage
add_rewrite_rule( $regex, $query, $after );
- $regex(string) (required)
- Regular expression to match request against.
- $query(string|array) (required)
- The corresponding query vars for this rewrite rule.
- $after(string)
- Priority of the new rule. Accepts 'top' or 'bottom'.
Default: 'bottom'
Examples
#1 How to register a new rewrite rule
Here is a simple example of how to register a new rewrite rule, and pass it off to a PHP file for rendering:
1 - Setup a rule:
add_action( 'init', function() { add_rewrite_rule( 'myparamname/([a-z0-9-]+)[/]?$', 'index.php?myparamname=$matches[1]', 'top' ); } );
2 - Flush permalinks. Go to WP Admin > Settings > Permalinks > Save. This doesn’t happen automatically after you add this code
3 - Whitelist the query param:
add_filter( 'query_vars', function( $query_vars ) { $query_vars[] = 'myparamname'; return $query_vars; } );
4 - Add a handler to send it off to a template file:
add_action( 'template_include', function( $template ) { if ( get_query_var( 'myparamname' ) ) { return get_template_directory() . '/template-name.php'; } return $template; } );
#2 User-friendly URLs for pages
We create a "nutrition" page (nutrition, ID=12) to display various nutrition information on it. Then, this page uses a separate template. The request variables food
and variety
are passed to the page.
Let's replace the ugly URL: /nutrition?food=mush&variety=semolina
with the pretty ones: /nutrition/mush/semolina
add_action( 'init', 'do_rewrite' ); function do_rewrite(){ add_rewrite_rule( '^(nutrition)/([^/]*)/([^/]*)/?', 'index.php?pagename=$matches[1]&food=$matches[2]&variety=$matches[3]', 'top' ); // you need to specify ?p=123 if such a rule is created for post 123 // the first parameter for posts: p or name, for pages: page_id or pagename // tell WP that there are new query parameters add_filter( 'query_vars', function( $vars ){ $vars[] = 'food'; $vars[] = 'variety'; return $vars; } ); }
When using $matches[]
, the array keys start with 1
, not 0
.
Now you need to update the rewrite rules, to do this, just visit the Settings > Permalinks
page - the rules will update in the WP options.
You can get the parameters in the page code through the get_query_var() function. For example, link: /nutrition/mush/semolina
echo get_query_var('food'); // mush echo get_query_var('variety'); // semolina
By default, WordPress does not recognize new query variables used for rewrite. You need to register them with add_rewrite_tag() or through the filter query_vars
, if not done, the rewrite rule will not work.
To make a rule work, you must update (reset) the rules in the database. To do this, call function flush_rules(). Or just go to Settings -> Permalinks
where flush_rules() will automatically triggered.
#3 Friendly URL for the page (example 2)
Another example of creating an Friendly URL for a static page. First the code:
// rewrite rule for the sitemap page add_action( 'init', 'rewrite_rule_my' ); function rewrite_rule_my(){ add_rewrite_rule( '^(sitemap)/([^/]*)/?', 'index.php?pagename=$matches[1]&pagetype=$matches[2]', 'top' ); add_rewrite_tag( '%pagetype%', '([^&]+)' ); }
Here we created the Friendly URL for the permanent page /sitemap?pagename=value
(pagename is a query variable). After placing this code in theme functions.php, the Friendly URL of the following form will start working: /sitemap/value
and in PHP on this page, you can use the variable $wp_query->query_vars['pagetype']
, which will contain the value value
. Or you can get the value like this: get_query_var('pagetype')
.
#4 Friendly URL for a child page
In the parameter pagename
we need to pass the whole link, not just the page slug. Suppose the URL of our child page is /parent/slug
, then:
add_rewrite_rule( '^(parent/slug)/([^/]*)', 'index.php?pagename=$matches[1]&foo=$matches[2]', 'top' );
That is, in the regular expression you should write (parent/slug)
instead of parent/(slug)
.
WP will now begin to understand URLs of the form /parent/slug/value
, where value will be available through get_query_var('foo')
.
#5 Redirect to scripts other than index.php
Using rewrite rules to redirect to scripts other than index.php
.
The $redirect
argument works differently when redirecting to a non index.php
PHP script. In this case, WordPress passes these redirects to .htaccess
instead of handling them itself.
For this reason, variables should be written as $1
instead of $matches[1]
.
add_action( 'init', 'custom_rewrite_rule', 10, 0 ); function custom_rewrite_rule() { add_rewrite_rule( 'nutrition/([^/]*)/([^/]*)/?', 'path/to/script.php?food=&variety=', 'top' ); }
When adding such a rule -- see WP_Rewrite::add_rule() -- WP checks if there is a index.php
file in the $redirect parameter -- see property WP_Rewrite::$index -- if it is not there, control is given to WP_Rewrite::add_external_rule() method.
It adds the rewrite rule to a separate non_wp_rules
array: see WP_Rewrite::$non_wp_rules. Later data from this array will go directly to .htaccess
.
That is, after installing the code above and updating rewrite rules, you will have a new rule (line 7) in .htaccess
:
# BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase / RewriteRule ^index\.php$ - [L] RewriteRule ^nutrition/([^/]*)/([^/]*)/? /path/to/script.php?food=&variety= [QSA,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress
Another example: Friendly login link
This is just an example with no practical use. WordPress since version 3.0 automatically redirects to /wp-login.php
if we try to go to /login
.
If we type http://example.com/login
into the browser line, we open the login page http://example.com/wp-login.php
(the URL will not change - there will be no redirect):
// Let's make http://site.com/login count as a request for http://site.com/wp-login.php add_action( 'init', 'wp_pretty_login' ); function wp_pretty_login() { add_rewrite_rule( 'login$', 'wp-login.php', 'top' ); }
Get in .htaccess:
# BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase / RewriteRule ^index\.php$ - [L] RewriteRule ^login$ /wp-login.php [QSA,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress
Notes
- Global. WP_Rewrite. $wp_rewrite WordPress rewrite component.
Changelog
Since 2.1.0 | Introduced. |
Since 4.4.0 | Array support was added to the $query parameter. |
add_rewrite_rule() add rewrite rule code WP 6.3
function add_rewrite_rule( $regex, $query, $after = 'bottom' ) { global $wp_rewrite; $wp_rewrite->add_rule( $regex, $query, $after ); }