requestfilter-hookWP 2.1.0

Filters the parameters (variables) of the main WordPress query.

The main query is the query associated with the current page. A category page, for example, has one set of query variables, while a search page has another.

When the request hook fires

It fires while the main query is being built, after the init event. Let us break down the process.

The main query is built by wp(), which is based on WP::main(). This is essentially what the documentation means when it says that wp() sets up the WordPress environment. The code shows how the environment is initialized:

//
public function main($query_args = '') {
	$this->init();                      // Sets the current user
	$this->parse_request($query_args);  // Parses the supplied query parameters and URL rewrite parameters
	$this->send_headers();              // Sends header() headers
	$this->query_posts();               // Retrieves posts using the query parameters
	$this->handle_404();                // Sets 404 status if the query found no posts
	$this->register_globals();          // Sets WordPress global variables:
										// $query_string, $posts, $post, $request, $more, $single, $authordata

	// Fires after the WordPress environment has been set up
	do_action_ref_array( 'wp', array( &$this ) );
}

The code comments describe what happens. The request filter fires at the end of WP::parse_request() and can change the WP::query_vars property. This property contains the query variables used by WP::query_posts(), which retrieves the posts.

Another hook: parse_request, an extended counterpart of request

do_action_ref_array( 'parse_request', array( &$this ) );

It passes the complete WP object by reference, allowing us to change not only its $query_vars property but other properties as well. In most cases, however, $query_vars is exactly what needs to be changed.

Another hook: pre_get_posts, an alternative to request

See pre_get_posts.

pre_get_posts fires for every query, not only the main query. It runs whenever get_posts(), query_posts(), or WP_Query is invoked.

For the main query shown above, it fires during WP::query_posts(), after the request filter.

Usage

add_filter( 'request', 'wp_kama_request_filter' );

/**
 * Function for `request` filter-hook.
 * 
 * @param array $query_vars The array of requested query variables.
 *
 * @return array
 */
function wp_kama_request_filter( $query_vars ){

	// filter...
	return $query_vars;
}

Parameters

$query_vars(array)
Query parameters to change (filter).

Examples

#1 Parameters set on different pages

// Home page: `example.com`
Array (  )

// Single post: http://example.com/my_post_name/
Array ( [page] => [name] => my_post_name )

// Static page: http://example.com/my_page/
Array ( [page] => [pagename] => my_page )

// Category page: `example.com/category/cars/`
Array ( [category_name] => uncategorized )

// Tag page: http://example.com/tag/another-tag/
Array ( [tag] => another-tag )

// Author page: http://example.com/author/admin
Array ( [author_name] => admin )

// Date archive: http://example.com/2016/10/08/
Array ( [year] => 2016 [monthnum] => 10 [day] => 08 )

#2 Change the RSS feed address to any other address

You can create any feed, such as an Atom feed. Create a page and replace its query. In this example, the page is named feed-yandex-zen.

add_filter( 'request', 'zen_url_replace' );
function zen_url_replace( $query_vars ) {
	if ( isset( $query_vars['pagename'] ) && $query_vars['pagename'] == 'feed-yandex-zen' ) {
		unset( $query_vars );
		$query_vars['feed'] = 'zen';
	}

	return $query_vars;
}

#3 Pagination for a static page with the category slug

Change the query so pagination works on the category page. A page with the category slug must be created in the admin panel and selected as the Posts page under Reading settings.

The page template must contain the standard WordPress loop.

/**
 * Changes the query so pagination works on the category page.
 *
 * The category page must be created in the admin panel
 * and selected as the Posts page under Reading settings.
 *
 * $param array $query_vars
 *
 * @return array
 */
add_filter( 'request', function ( $query_vars ) {

	if ( isset( $query_vars['category_name'] ) ) {
		$page = explode( '/', $query_vars['category_name'] );

		if ( $page[0] == 'page' ) {
			$paged = isset( $page[1] ) && is_numeric( $page[1] ) ? (int) $page[1] : 0;

			$query_vars['page']     = '';
			$query_vars['pagename'] = 'category';
			$query_vars['paged']    = $paged;

			unset( $query_vars['category_name'] );
		}
	}

	return $query_vars;
} );

#4 Display posts on a specified static page

add_filter( 'request', function ( $query_vars ) {
	$page_id    = 484;
	$page_slug  = 'all-articles';

	if ( isset( $query_vars['pagename'] ) && $query_vars['pagename'] === $page_slug ) {
		add_filter( "pre_option_page_for_posts", function () {
			return $page_id;
		} );
	}

	return $query_vars;
} );

#5 Make the sitemap page available at sitemap.html

Suppose the site uses the /%postname%/ permalink structure, but an HTML sitemap must be available at example.com/sitemap.html. Create a page with slug = sitemap that generates the HTML sitemap using a plugin or custom code; the following code handles the rest:

add_filter( 'request', 'add_sitemap_html' );

function add_sitemap_html( $query_vars ) {
	// Check whether sitemap.html was requested
	if ( isset( $query_vars['name'] ) && $query_vars['name'] == 'sitemap.html' ) {
		// Replace the query with data for the page whose slug is sitemap
		$query_vars = [
			'page'     => '',
			'pagename' => 'sitemap',
		];

		// Remove the redirect to a URL with a trailing slash
		remove_action( 'template_redirect', 'redirect_canonical' );
	}

	return $query_vars;
}

#6 Change a category URL

Suppose we have the /category/cars/ category and need /category/cars/super-cars/ to display that same category.

add_filter( 'request', 'my_request' );
function my_request( $query_vars ){

	$request = urldecode($_SERVER['REQUEST_URI']);

	if( $request == '/category/cars/super-cars/' ){
		$query_vars['category_name'] = 'cars';
	}

	return $query_vars;
}

#7 Display the standard feed at a specified URL

Some services require a feed with an XML extension, such as news.xml. Make the standard WordPress feed available at such a URL.

add_filter( 'request', function ( $query_vars ) {
	// Request to domain/news.xml
	if ( [ 'page' => '', 'name' => 'news.xml' ] === $query_vars ) {
		// Replace the query variables with those used at domain/feed/
		$query_vars = [ 'feed' => 'feed' ];

		// Replace REQUEST_URI to prevent a redirect to the empty domain/news.xml/feed/ feed
		$_SERVER['REQUEST_URI'] = '/feed/';
	}

	return $query_vars;
} );

The same can be done on the init hook:

add_filter( 'init', function () {
	if ( $_SERVER['REQUEST_URI'] === '/news.xml' ) {
		$_SERVER['REQUEST_URI'] = '/feed/';
	}
} );

Changelog

Since 2.1.0 Introduced.

Where the hook is called

WP::parse_request()
request
wp-includes/class-wp.php 409
$this->query_vars = apply_filters( 'request', $this->query_vars );

Where the hook is used in WordPress

wp-includes/default-filters.php 599
add_filter( 'request', '_post_format_request' );