Using Pre_Get_Posts To Modify The Main Query In WordPress

What is the Main Query?

The main query in WordPress refers to the default WordPress query that runs on archive and homepage pages. It retrieves posts from the database and displays them according to the site’s settings and configurations.

When you load a page in WordPress, the main query executes behind the scenes to fetch the posts to display on that page. It pulls posts based on parameters like post type, number of posts per page, categories, tags, custom fields, etc.

The main query powers the core functionality of listing and displaying posts in WordPress. It appears on blog pages, archives, search results, and any page that shows multiple posts.

Why Modify the Main Query?

There are several reasons you may want to modify the main WordPress query:

  • Change the number of posts displayed per page
  • Include custom post types in index and archive pages
  • Exclude specific categories from paginated pages
  • Order posts by custom fields instead of date
  • Add pagination to the homepage
  • Display sticky posts first
  • Filter posts for complex queries

By modifying the main query, you can customize your WordPress site’s content display and achieve functionality that goes beyond the standard settings.

Using the pre_get_posts Action

The pre_get_posts action allows you to alter the main query before it executes. This action passes the WP_Query object, which you can then modify by changing its parameters and arguments.

To use pre_get_posts, you add a function to functions.php that hooks into the action. Your callback function receives the $query argument, which gives you access to modify the main query programmatically.

add_action( 'pre_get_posts', 'my_pre_get_posts' );
 
function my_pre_get_posts( $query ) {

  // Query modifications go here

}

Within the callback function, you can use conditionals to target specific pages and make changes only when necessary. This allows you to modify queries selectively for fine-tuned control.

Modifying the Posts Per Page

One very common use of pre_get_posts is to change the number of posts displayed per page in WordPress.

By default, WordPress shows 10 posts per page. You can easily modify this number to show more or fewer posts on archive index pages.

add_action( 'pre_get_posts', 'change_posts_per_page' );
 
function change_posts_per_page( $query ) {

  if ( $query->is_main_query() && !is_admin() ) {
    $query->set( 'posts_per_page', 8 );
  }

}  

The code above changes the query to display 8 posts per page instead of the default 10. The conditional checks make sure it only applies this modification to the front-end main query.

Including Custom Post Types

By default, only the built-in post post type appears on blog index and archive pages in WordPress. To display custom post types, you need to modify the main query with pre_get_posts.

For example, to add a custom “Movie” post type to the main blog feed, you would add:

add_action( 'pre_get_posts', 'add_custom_post_types' );
 
function add_custom_post_types( $query ) {

  if ( $query->is_home() && $query->is_main_query() ) {
    $query->set( 'post_type', array('post', 'movie') );
  }

}

Now the main WordPress loop will include both regular posts and movies. This makes custom post types visible along with standard posts.

Excluding Categories

When using pagination on category and archive pages, you may want to exclude some categories from the main query.

For example, to remove the “Uncategorized” and “Announcements” categories from paginated archive indexes, you would use:

add_action( 'pre_get_posts', 'exclude_categories' );
 
function exclude_categories( $query ) {

  if ( $query->is_archive() && $query->is_main_query() && $query->is_paged() ) {
    $query->set( 'category__not_in', array(1, 3) );
  }

} 

This prevents those categories from appearing on any paginated archive pages, while still displaying them on the first main archive page.

Ordering Posts by Custom Fields

You can also order posts by custom field values instead of publishing date with pre_get_posts.

For example, to sort posts by a number field called “priority”, you would add this to functions.php:

add_action( 'pre_get_posts', 'order_by_priority' );
 
function order_by_priority( $query ) {

  if ( $query->is_main_query() ) {
    $query->set( 'orderby', 'meta_value_num' );
    $query->set( 'meta_key', 'priority' );
  }

}

Now posts will order by the priority number field in descending order (high to low).

Additional Tips and Examples

Here are some other helpful tips for modifying the main query in WordPress:

  • Add pagination to the homepage by checking $query->is_home()
  • Display sticky posts first with $query->set( ‘ignore_sticky_posts’, 0 )
  • Filter by complex meta queries for custom fields
  • Modify the ordering direction with $query->set( ‘order’, ‘ASC’ )
  • Search by custom taxonomy parameters

The possibilities are vast when tapping into the main query. Refer to the WP_Query documentation for more parameter options and examples.

Summary

The main WordPress query controls the posts displayed across archive and blog pages. Using the pre_get_posts action allows you to modify the query for advanced customizations.

Reasons to alter the main query include:

  • Changing number of posts per page
  • Adding custom post types
  • Excluding categories
  • Ordering by custom fields
  • And more…

Leveraging pre_get_posts opens up tremendous flexibility to customize WordPress content display beyond the admin settings. It’s a powerful tool for developers and advanced sites.

Leave a Reply

Your email address will not be published. Required fields are marked *