Using Wp_Query Vs. Query_Posts() For Custom Loops In WordPress
WP_Query and query_posts() are two functions in WordPress used to customize the main query and create secondary custom queries. While they share some functionality, there are important differences in their purpose, use cases, and best practices.
Purpose and Functionality Differences
WP_Query is used to fully customize secondary queries that run independently of the main query. It offers advanced querying functionality for fetching posts, pages, custom post types, users, and more. WP_Query gives developers complete control and flexibility.
In contrast, query_posts() is intended for minor alterations to the main query only. It lacks the parameters and filters available in WP_Query. query_posts() simply overrides the main query variables for that request, rather than creating an entirely custom secondary query.
When to Use WP_Query vs query_posts()
WP_Query for custom queries
WP_Query should be used anytime you need to query data in a custom way, outside of the default main query. For example, to display related posts, create filtered archive pages, or populate custom Page templates.
WP_Query allows querying by any type of parameter, including:
- Post IDs, post types, statuses, etc.
- Authors, taxonomies, terms, meta values
- Dates, custom fields, search parameters
- Page IDs, page parents, page templates
- And more…
It also offers complete control over query parameters like posts_per_page, pagination, caching, query ordering, and filtering.
query_posts() for simple main loop modifications
query_posts() is intended for minor tweaks to main query, such as on category and archive pages. Common examples include:
- Reduce posts on busy archive pages
- Integrate ads every X posts in main loop
- Small pagination adjustments
These are cases where you still want to largely rely on the main loop, but just tweak parts of the default query variables.
WP_Query Advantages
Compared to query_posts(), WP_Query has some important advantages:
More flexibility and control
As outlined above, WP_Query supports a much wider range of query parameters and gives developers full control over every aspect.
Better performance
WP_Query queries run independently without affecting caches or object caching from the default query. This prevents performance issues.
Avoid breaking main query
Overriding the main query with query_posts() can lead to unexpected breaks across various templates and plugins relying on the default query. WP_Query is self-contained.
query_posts() Drawbacks
However, query_posts() does come with some drawbacks to be aware of:
Alters main query
Any adjustments made in query_posts() are applied to the global $wp_query object, overriding default query vars. This can produce unintended consequences across themes and plugins.
Performance impacts
Modifying the main query prevents proper caching, since that query is used across most templates. Too many query tweaks results in redundant post objects and database queries.
Less flexibility
query_posts() only allows adjusting a limited subset of query parameters compared to WP_Query. Complex queries are not possible.
Example WP_Query Usage
WP_Query usage depends on the specifics of the custom query, but some examples include:
Basic custom post query
$args = array( 'post_type' => 'projects', 'posts_per_page' => 10 ); $query = new WP_Query( $args );
Query by taxonomy parameters
$args = array( 'post_type' => 'post', 'tax_query' => array( array( 'taxonomy' => 'category', 'field' => 'slug', 'terms' => 'news', ), ), ); $query = new WP_Query( $args );
Meta queries
$args = array( 'post_type' => 'post', 'meta_key' => 'priority', 'orderby' => 'meta_value', 'order' => 'ASC', 'meta_query' => array( array( 'key' => 'priority', 'value' => 'high', ), ), ); $query = new WP_Query( $args );
Date parameters
$args = array( 'date_query' => array( array( 'after' => '1 month ago', 'before' => 'January 1st, 2022', 'inclusive' => true, ), ), ); $query = new WP_Query( $args );
Example query_posts() Usage
query_posts() has a simpler syntax focused mainly on adjusting posts_per_page and order/orderby parameters:
Simple main loop modification
function customize_home( $query ) { if ( $query->is_home() && $query->is_main_query() ) { $query->set( 'orderby', 'rand' ); } } add_action( 'pre_get_posts', 'customize_home' );
Best Practices and Recommendations
When working with custom queries, we recommend:
Use WP_Query for custom secondary loops
WP_Query is the best way to create targeted secondary loops with advanced querying functionality. This avoids impacting caching and performance.
Avoid using query_posts() in plugins/themes
Overuse of query_posts() causes main query overrides that can break expected template behavior. Use with caution.
Consider caches and edge cases
Carefully test custom queries to ensure proper caching, site performance, and expected behavior across themes and plugins relying on the main query.