Voxfor - All rights reserved - 2013-2025
We Accepted





WordPress is an open-source platform that is known for its flexibility, allowing developers to customize almost every aspect of the platform to suit specific needs. One of the most useful tools for developers is the pre_get_posts in WordPress. This hook allows you to modify main query conditions under specific circumstances, thereby enabling smooth post-page-custom post-type output control.
This article covers pre_get_posts action implementation strategies alongside WordPress core compatibility and retains pagination functionality. By the end, you’ll have a clear understanding of how to modify the main query dynamically and safely.
The pre_get_posts action is triggered just before WordPress executes the main query. The main query determines what content to display on the current page, such as posts on the home page, a single post, or an archive. By hooking into pre_get_posts, you can modify this query before WordPress retrieves the results from the database.
For example:
Historically, developers used query_posts() to modify queries, but this approach has significant drawbacks. Using query_posts() overwrites the main query and creates a secondary query, which can break functionality like pagination and lead to performance issues.
These action solves problems by allowing you to modify the original query safely without overwriting it. This method ensures that WordPress correctly handles pagination and other features.
To use pre_get_posts, you must hook into it using the add_action() function in your theme’s functions.php file or a custom plugin. Here’s a basic example:
add_action('pre_get_posts', 'modify_main_query');
function modify_main_query($query) {
ย ย ย ย // Always check if it's the main query
ย ย ย ย if (!$query->is_main_query()) {
ย ย ย ย ย ย ย ย return;
ย ย ย ย }
ย ย ย ย // Example: Modify the home page query
ย ย ย ย if ($query->is_home()) {
ย ย ย ย ย ย ย ย $query->set('posts_per_page', 5);
ย ย ย ย }
}
One of the most critical steps is ensuring you’re modifying only the main query and not any secondary queries. Use $query->is_main_query() to verify this.
if (!$query->is_main_query()) {
ย ย ย ย return;
}
This validation process helps you focus on WordPress main query, which is responsible for paginating content on the current display page. In the absence of this check, you could make modifications to other queries which would result in unpredictable behavior.
Let’s dive into some common use cases for modifying the main query.
To change the number of posts displayed on the home page:
add_action('pre_get_posts', 'custom_home_page_query');
function custom_home_page_query($query) {
ย ย ย ย if ($query->is_main_query() && $query->is_home()) {
ย ย ย ย ย ย ย ย $query->set('posts_per_page', 10); // Display 10 posts per page
ย ย ย ย }
}
If you have a custom post type (e.g., “products”) and want to include it on your archive page:
add_action('pre_get_posts', 'add_custom_post_type_to_archive');
function add_custom_post_type_to_archive($query) {
ย ย ย ย if ($query->is_main_query() && $query->is_post_type_archive('products')) {
ย ย ย ย ย ย ย ย $query->set('posts_per_page', 12); // Display 12 products per page
ย ย ย ย }
}
To exclude posts from a specific category (e.g., “Uncategorized”) on the blog page:
add_action('pre_get_posts', 'exclude_category_from_blog');
function exclude_category_from_blog($query) {
ย ย ย ย if ($query->is_main_query() && $query->is_home()) {
ย ย ย ย ย ย ย ย $query->set('cat', '-1'); // Exclude category with ID 1
ย ย ย ย }
}
To display posts from multiple categories:
add_action('pre_get_posts', 'include_categories_in_archive');
function include_categories_in_archive($query) {
ย ย ย ย if ($query->is_main_query() && $query->is_archive()) {
ย ย ย ย ย ย ย ย $query->set('category__in', [2, 3, 4]); // Include categories with IDs 2, 3, and 4
ย ย ย ย }
}
You can customize search results to include specific post types or exclude certain content:
add_action('pre_get_posts', 'customize_search_results');
function customize_search_results($query) {
ย ย ย ย if ($query->is_main_query() && $query->is_search()) {
ย ย ย ย ย ย ย ย $query->set('post_type', ['post', 'page']); // Include posts and pages in search
ย ย ย ย ย ย ย ย $query->set('posts_per_page', 15); // Limit search results to 15 per page
ย ย ย ย }
}
Target Only the Front-End Queries
Always ensure that your modifications apply only to the front end by excluding admin queries:
if (is_admin()) {
ย ย ย ย return;
}
Without this check, your changes might affect queries in the WordPress admin area, potentially causing errors or unexpected results.
When working with pre_get_posts, debugging is essential to ensure your changes are applied correctly. Here are some tips:
Log the Query
Use the error_log() function to check the query variables:
error_log(print_r($query, true));
Enable Debug Mode
Set WP_DEBUG to true in your wp-config.php file to display PHP errors and warnings:
define('WP_DEBUG', true);
Use Plugins
Plugins like Query Monitor or Debug Bar can help you inspect queries and understand how your changes affect the output.
Through the pre_get_posts action, users can modify WordPress queries without damaging core features such as pagination. By targeting main queries while avoiding query_posts() breakdown and conducting thorough tests, content displays that match your site requirements become achievable. Whether you’re working with custom post types, categories, or taxonomies, pre_get_posts offers a clean, efficient way to control how content is displayed on your site.
Hassan Tahir wrote this article, drawing on his experience to clarify WordPress concepts and enhance developer understanding. Through his work, he aims to help both beginners and professionals refine their skills and tackle WordPress projects with greater confidence
Jacob Anderson
The pre_get_posts action in WordPress offers developers a powerful way to customize queries without breaking pagination or performance. By hooking into it, you can easily modify content display for various use cases like post count, categories, and custom post types.