Current query, pre_get_posts practical uses

Current query, pre_get_posts practical uses

Online by JSC0d3
July 25, 2017 | | | | 2363 recognitions

pre_get_posts” is a WordPress hook that allows you to modify the current query. Just a quick reminder: when you’re visiting any page of a WordPress install, the system creates a query that depends on the url you’re visiting. This is basically what the template hierarchy does.  The “pre_get_posts” hook is called after the query variable object is created, but before the actual query is run. That’s why this allows you to modify the query before results are printed on your screen. That’s pretty useful to modify for example an archive page, the results of a search, or a custom post type page. Here’s an info about “pre_get_posts” in the codex:

The pre_get_posts action gives developers access to the $query object by reference (any changes you make to $query are made directly to the original object – no return value is necessary).

That’s important to note that the $query object passed to your function is passed by reference. That’s to say that you don’t need to declare globals variables and you don’t need to return a value. Any changes you make to the object from inside your function are made to the original immediately.

Current query, pre_get_posts practical uses

In WordPress, pre_get_posts is a filter that makes it possible to modify an existing WP_Query, before that query is actually run. pre_get_posts offers some solutions that are more performant than writing a custom WP_Query, and enables solutions to other problems that would be quite difficult otherwise.

What a WP_Query Is

In programming, to query a database generally means to fetch specific results out of that database. For example, in a database full of person data, you might want a specific person’s name and age, and you’d write a query (in SQL or a similar language) to fetch the information you want.

A WP_Query is a special type of query, unique to WordPress, that fetches posts from the WordPress database. WordPress posts are the blocks of content that make up a site’s blog articles, pages, media attachments, and more.

As we cover in our introduction to WP_Query, almost every page on a WordPress site is created by looping through one or more bundles of posts. These post bundles are fetched by the default WP_Query that WordPress runs for that page type, and may also be fetched by one or more custom WP_Querys we write ourselves.


pre_get_posts is a filter that lets you modify a WP_Query that is “about to run,” meaning “about to ask the database for a post bundle.” Before the query can run off to the database and get its bundle of posts, we’re going to swoop in and change which posts the query will actually request. This order of events is how pre_get_posts gets its name.

pre_get_posts is a filter that lets you modify a WP_Query that is about to run.

For example, the following pre_get_posts example will cause your blog index page, which normally lists your most recent posts of type Post, to instead list your most recent posts of type Page:

add_filter( 'pre_get_posts', 'js_pages_blogindex' );
function js_pages_blogindex( $query ) {
	if ( is_home() && $query->is_main_query() ) :
		$query->set( 'post_type', 'page' );

Pasting this code into the live theme’s functions.php leads to a (rather odd) blog index with only Pages and no Posts.

So pre_get_posts let us modify the blog index’s already existing default query, without us having to write a new WP_Query ourselves. That’s pre_get_posts in a nutshell.

When to Use pre_get_posts

Remember, pre_get_posts lets you modify an existing query. So pre_get_posts is useful when it’s best not to write a new query, but to change one that already exists. Here are a few examples:

Some Custom WP_Querys are Easiest to Modify with pre_get_posts

Sometimes you need to modify a custom WP_Query that you didn’t write. This most likely means a query from an external plugin, or from somewhere in WordPress core.

As an example, the “Recent Posts” widget is a part of WordPress core. Let’s say that we’re using “Recent Posts” on our site, and that we’ve just created a page called “Fundraiser.” On our Fundraiser page, and that page alone, we want the “Recent Posts” widget to only show recent posts that are tagged with “fundraiser.”

We could install a better “Recent Posts” widget that allows this, and then make a custom widget area exclusively for the “Our Fundraiser” page, but that creates quite a bit of clutter. Instead, let’s just conditionally modify the custom WP_Query that “Recent Posts” uses. That process has three steps:

  1. Make sure we’re on the “Fundraiser” page,
  2. Make absolutely sure we’re talking to the custom query generated by “Recent Posts” (the hardest part), and
  3. Modify that query to our liking.

Here’s the code:

add_filter( 'pre_get_posts', 'js_raiser_recent_posts' );
function js_raiser_recent_posts( $query ) {
	// Do nothing if not on raiser page
	if( ! is_page( 'raiser' ) ) :

	// Make sure we're talking to the WP_Query
	// generated by the Recent Posts widget
	if( ! is_main_query() &&
		$query->query[ 'no_found_rows' ] === true &&
		$query->query[ 'post_type' ] === NULL
	) :

		// Fetch only posts tagged with "fundraiser"
		$taxquery = array(
				'taxonomy' => 'post_tag',
				'field' => 'slug',
				'terms' => array( 'raiser' ),
		$query->set( 'tax_query', $taxquery );


A bit of a convoluted example, but still probably quicker and cleaner than the alternatives if this was a real project.

Modifying WordPress Default Queries

WordPress’s default queries are extremely important: they’re the queries that fetch the most recent Posts for your blog index, all Posts of a specific category for a Category archive page, all posts from a specific month for a month-based archive page, search results for a search page, and so on.

Most of the time you’ll use pre_get_posts on WordPress’s default queries, since you can usually modify other queries directly.

In the previous section, I stretched my brain to find a case where you’d use pre_get_posts to modify a custom WP_Query. However, most of the time you’ll be using pre_get_posts on WordPress’s default queries, since you can usually modify other queries directly. (Almost every example on the Codex documentation for pre_get_posts modifies a page’s default query.)

pre_get_posts is the best way to modify a default query. Here’s an important example from last week’s article on custom post types, causing a newly registered custom post type, Courses, to show up on the site’s archive pages, which wouldn’t happen by default:

// Make Courses posts show up in archive pages
add_filter( 'pre_get_posts', 'js_add_custom_post_types_to_query' );
function js_add_custom_post_types_to_query( $query ) {
		is_archive() &&
		empty( $query->query_vars['suppress_filters'] )
	) {
		$query->set( 'post_type', array( 
		) );

This code first asks if we’re on an archive page. If we are, it modifies the page’s default query to pull in not only Posts, but also Courses.

The alternative to this approach—modify whichever template uses the default query you want to change (index.php, search.php, etc.), remove the template’s default query processing, and then write your own custom WP_Query from scratch—is both brittle and way too much work. For example, I’d have no idea how to write a single custom WP_Query to cover all the different kinds of queries that get generated for archive pages.

Check out the Codex for lots of other commonsense examples that relate to hiding a specific post from search results, modifying the categories that the blog index pulls in, and so on.

pre_get_posts is More Performant than Writing a New WP_Query

In some situations, you could use either pre_get_posts or a new custom WP_Query to do what you want. In those situations, it’s faster and better to use pre_get_posts, because you only make one trip—and not two—to the WordPress database. Remember, every WP_Query is a new, complex query that will be sent to the WordPress database. One modified database query will process a lot quicker than two completely separate queries.

Now You Can pre_get_posts

Working with pre_get_posts is a very helpful tool to have in your pocket if you’re running into queries you can’t modify. It’s also an excellent way to prevent writing unnecessary custom WP_Querys when it’s both simpler and more performant to modify and existing query. This is especially true when you need to make changes to WordPress’s default queries, for pages like your blog index, archive, and search pages; that’s where pre_get_posts becomes indispensable.


As we saw, “pre_get_posts” is really powerful and can really helps you to customize the current query. This is also a good method to modify a query made from a plugin without modify the core plugin files (or the theme core files). So i really encourage you to have a deep leep to that hook and use it in your own developments!

JSC0d3's Logo
About JSC0d3

JSC0d3 is an entrepreneur, online marketer, and an employee of an IT company. When not building websites, creating content, or helping customers improve their online business, spend time with their wife and two beautiful children. Although he still feels new in WordPress, he enjoys sharing what he has learned with all of you! If you want to get in touch with him, you can do this through this website.

On the same idea

Posted by | February 9, 2019

How fast your website loads can have a direct effect on whether you turn visitors into new customers and fans When your site is delivered to...

Posted by | February 9, 2019

With today’s high-speed internet connections and advances in web development techniques, there is no reason that your website should be...

Posted by | February 9, 2019

WordPress' wp_link_pages() function, used for displaying page links in multi-page posts, lacks one big feature You can display a list of...

Previous PostBackNext Post
2 impressions on “Current query, pre_get_posts practical uses

Amar Patel,

Thanks for all your efforts on this website. Most of us notice all concerning the powerful tactic you provide practical strategies via the website and even increase contribution from other ones on the topic plus our own girl is actually becoming educated a lot. Have fun with the rest of the year. You are carrying out a useful job.

J&S Code,

Very nice of you, thank you very much.

Leave here an impression