WP Query Functions – What to use and when

GP Web Dev - Feb 27 - - Dev Community

Core WordPress functions and classes are generally excellent regarding to performance and security.

When it comes to retrieving data from the database, the WP_Query class and its methods provide us with a safe and efficient way to do it, avoiding complex SQL queries. There are some additional wrappers of WP_Query, like query_posts() and get_posts().


query_posts

WordPress Codex explicitly says “Its overly-simplistic approach to modifying the main query can be problematic and should be avoided wherever possible“.

This query wrapper is inefficient (re-runs SQL queries) and will fail in some circumstances, especially when dealing with posts pagination. It instantiates a new WP_Query object and reassigns that to the global wp_query, breaking the main query that many plugins, themes and custom scripts rely on. For secondary queries (custom loops) instantiate your own WP_Query.

Use new WP_Query or get_posts() which are pretty much interchangeable (latter is thin wrapper for former). If you do want to alter the main query, then use the pre_get_posts hook with $query->is_main_query() check. pre_get_posts is a filter for altering any query and it is most often used to alter the ‘main query’. This is the trac about the deprecation of query_posts.

Therefore:

You should never use query_posts().


get_posts

This is essentially a wrapper for a separate instance of a WP_Query object. This isn’t a ‘Loop’, it simply returns an array of post objects.

It accepts the same arguments as WP_Query, doesn’t modify global variables and is safe to use anywhere. It passes 'no_found_rows' => true by default so it is used for non paginated queries only. It ignores sticky posts, needs just a foreach loop to display the $post property and requires a setup_postdata( $post ) to make the template tags available. WP_Query uses the loop and template tags are available by default.

Use get_posts() for some quick, non-paginated, data fetch.


WP_Query

WP_Query is the class behind both the above functions. The power of WP_Query derives from the possibility to create and work with your own instance of it. It is more of a general purpose tool, similar to directly writing MySQL, for a detailed custom query script.

A bit more complex with fewer restrictions, thus making it more powerful while being safe to use anywhere.

Use a new WP_Query for an in-depth, flexible query script.


Reset/Cleanup

  • Use wp_reset_query() if you’ve used query_posts() or altered global $wp_query directly – hopefully you will never need to.
  • Use wp_reset_postdata() if you’ve used the_post() or setup_postdata() to restore initial state of global $post.

Performance

All queries are eventually wrappers of WP_Query, and while some are better than other (never use query_posts), the performance differences of get_posts vs WP_Query are negligible. The WP_Query is faster than get_posts by a very small margin.

However parameters provided by the WP_Query class can specifically optimize SQL queries, reducing execution time and resource consumption. (Ref. 1 | 2)

  • When we don’t need pagination, we should set no_found_rows to true, making the query run dramatically faster.
  • When specific fields are not required, limit the returned fields to IDs: 'fields' => 'ids'

. . . .