wppaste
WordPress

WP_Rewrite::generate_rewrite_rules( string $permalink_structure, int $ep_mask = EP_NONE, bool $paged = true, bool $feed = true, bool $forcomments = false, bool $walk_dirs = true, bool $endpoints = true ): string[]

Since
1.5.0
Source
wp-includes/class-wp-rewrite.php:874
Generates rewrite rules from a permalink structure.

Description

The main WP_Rewrite function for building the rewrite rule list. The contents of the function is a mix of black magic and regular expressions, so best just ignore the contents and move to the parameters.

Compatibility

WordPress
since 1.5.0
PHP
7.4–8.6-dev
  • 6.7.7
  • 6.8.8
  • 6.9.7
  • 7.0.4
  • 7.1.0

Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.

Parameters

$ep_maskintoptional
Endpoint mask defining what endpoints are added to the structure.
Accepts a mask of:
- EP_ALL
- EP_NONE
- EP_ALL_ARCHIVES
- EP_ATTACHMENT
- EP_AUTHORS
- EP_CATEGORIES
- EP_COMMENTS
- EP_DATE
- EP_DAY
- EP_MONTH
- EP_PAGES
- EP_PERMALINK
- EP_ROOT
- EP_SEARCH
- EP_TAGS
- EP_YEAR Default EP_NONE.Default: EP_NONE
$pagedbooloptional
Whether archive pagination rules should be added for the structure.
Default true.Default: true
$feedbooloptional
Whether feed rewrite rules should be added for the structure.
Default true.Default: true
$forcommentsbooloptional
Whether the feed rules should be a query for a comments feed.
Default false.Default: false
$walk_dirsbooloptional
Whether the 'directories' making up the structure should be walked over and rewrite rules built for each in-turn. Default true.Default: true
$endpointsbooloptional
Whether endpoints should be applied to the generated rewrite rules.
Default true.Default: true

Return value

string[]
Array of rewrite rules keyed by their regex pattern.

Performance profile

How much work a call to WP_Rewrite::generate_rewrite_rules() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.

Cost class
Heavy

Reads stored settings via get_option(), cached per request but not free on a cold cache.

Scaling
Scales with input

The body loops, so the work grows with what you pass in.

Instructions
510

Executed per call on PHP 8.5. The body compiles to 510.

Plugin surface
None

Nothing here hands control to plugin code.

Called by
3

3 places in core call this, so the cost is paid more often than your own code shows.

What it touches

  • optionoption read or writeget_option()called directly
  • hookthird-party callbacksapply_filters()one call below WP_Rewrite::generate_rewrite_rules()
  • cacheobject cachewp_cache_get()one call below WP_Rewrite::generate_rewrite_rules()
  • serializeserialisationmaybe_unserialize()one call below WP_Rewrite::generate_rewrite_rules()

Further down the call graph this can also reach query and transient. Those are the worst case, several calls deep and usually down an error path, not what a normal call pays.

Across PHP versions

PHPCompiledExecutedBranchesNotes
8.6-dev509509511 fewer instruction than PHP 8.5
8.551051051
8.45105105161 fewer instructions than PHP 8.3
8.357157151
8.2571571511 more instruction than PHP 8.1
8.1570570511 fewer instruction than PHP 7.4
7.457157151

An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.

Uses · 5

Used by · 3

Source code

	public function generate_rewrite_rules( $permalink_structure, $ep_mask = EP_NONE, $paged = true, $feed = true, $forcomments = false, $walk_dirs = true, $endpoints = true ) {		// Build a regex to match the feed section of URLs, something like (feed|atom|rss|rss2)/?		$feedregex2 = '';		foreach ( (array) $this->feeds as $feed_name ) {			$feedregex2 .= $feed_name . '|';		}		$feedregex2 = '(' . trim( $feedregex2, '|' ) . ')/?$'; 		/*		 * $feedregex is identical but with /feed/ added on as well, so URLs like <permalink>/feed/atom		 * and <permalink>/atom are both possible		 */		$feedregex = $this->feed_base . '/' . $feedregex2; 		// Build a regex to match the trackback and page/xx parts of URLs.		$trackbackregex = 'trackback/?$';		$pageregex      = $this->pagination_base . '/?([0-9]{1,})/?$';		$commentregex   = $this->comments_pagination_base . '-([0-9]{1,})/?$';		$embedregex     = 'embed/?$'; 		// Build up an array of endpoint regexes to append => queries to append.		if ( $endpoints ) {			$ep_query_append = array();			foreach ( (array) $this->endpoints as $endpoint ) {				// Match everything after the endpoint name, but allow for nothing to appear there.				$epmatch = $endpoint[1] . '(/(.*))?/?$'; 				// This will be appended on to the rest of the query for each dir.				$epquery                     = '&' . $endpoint[2] . '=';				$ep_query_append[ $epmatch ] = array( $endpoint[0], $epquery );			}		} 		// Get everything up to the first rewrite tag.		$front = substr( $permalink_structure, 0, strpos( $permalink_structure, '%' ) ); 		// Build an array of the tags (note that said array ends up being in $tokens[0]).		preg_match_all( '/%.+?%/', $permalink_structure, $tokens ); 		$num_tokens = count( $tokens[0] ); 		$index          = $this->index; // Probably 'index.php'.		$feedindex      = $index;		$trackbackindex = $index;		$embedindex     = $index; 		/*		 * Build a list from the rewritecode and queryreplace arrays, that will look something		 * like tagname=$matches[i] where i is the current $i.		 */		$queries = array();		for ( $i = 0; $i < $num_tokens; ++$i ) {			if ( 0 < $i ) {				$queries[ $i ] = $queries[ $i - 1 ] . '&';			} else {				$queries[ $i ] = '';			} 			$query_token    = str_replace( $this->rewritecode, $this->queryreplace, $tokens[0][ $i ] ) . $this->preg_index( $i + 1 );			$queries[ $i ] .= $query_token;		} 		// Get the structure, minus any cruft (stuff that isn't tags) at the front.		$structure = $permalink_structure;		if ( '/' !== $front ) {			$structure = str_replace( $front, '', $structure );		} 		/*		 * Create a list of dirs to walk over, making rewrite rules for each level		 * so for example, a $structure of /%year%/%monthnum%/%postname% would create		 * rewrite rules for /%year%/, /%year%/%monthnum%/ and /%year%/%monthnum%/%postname%		 */		$structure = trim( $structure, '/' );		$dirs      = $walk_dirs ? explode( '/', $structure ) : array( $structure );		$num_dirs  = count( $dirs ); 		// Strip slashes from the front of $front.		$front = preg_replace( '|^/+|', '', $front );

Changelog

Introduced in 1.5.0. Unchanged from 6.7.7 through 7.1.0.

  1. 6.7.7
  2. 6.8.8
  3. 6.9.7
  4. 7.0.4
  5. 7.1.0

Signature, return type and hooks compared across 5 parsed releases.

About this page

Parsed data
Generated from the wordpress-develop 7.1.0 tag, from src/wp-includes/class-wp-rewrite.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.
Corrections
Something wrong on this page? Report it and it gets fixed in the next regeneration.