request
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
$this->query_vars = apply_filters( 'request', $this->query_vars );
Where the hook is used in WordPress
add_filter( 'request', '_post_format_request' );