Worpress queries: When to use WP_Query, get_posts, query_posts or pre_get_posts
original source :Â http://beebell.co.uk/wordpress-queries-when-to-use-wp_query-get_posts-query_posts-pre_get_posts/
When youâre creating a custom theme, at some point you may to want to bring back a set of results other than what WordPress defaults to. The question is, do you use WP_Query,get_posts, Â query_posts or pre_get_posts?
Scenario 1 â You just need an archive page
Soluion: None of the above
If something can be accomplished without writing code, let WordPress do it for you.
If you want to move your main blog posts archive (ie. list of all your posts, usually just the excerpts) from the front page to another page (eg. a page entitled âBlogâ), all you need to do is:
a) create a new page called âBlogâ
b) Go to Settings > Reading and select âFront page displays: A static pageâ and select your posts page:
If you want an archive or single page for a custom post type, use the relevant templates from the template hierarchy. Eg. For a custom post type âbooksâ, use archive-books.php. Â The default loop will display all âbooksâ posts, and each individual post will be displayed with single-books.php. Â The exact link will depend on your permalink structure. If youâre using the âpost nameâ option (see Seetings > Permalinks) then http://yourdomain/books will automatically load your books archive template.
Scenario 2 â Your page already utilises a loop and you need an additional loop
Solutions: WP_Query or get_posts()
The difference between the two is that WP_Query returns an object and get_posts returns an array. Â If the content you want is fairly lightweight, for example a list of titles, then you can use get_posts and loop through the array with a foreach. Â If you want a fully blown WordPress Loop and the ability to use template tags such as the_content(), go for theWP_Query option.
Scenario 3 â you want to alter the main loop
Solutions: query_posts() or pre_get_posts
By the time Worpress loads your template and runs the code in your template, it has already run a query on the database and is holding the results ready for you to use in the loop. Â If you use query_posts to modify the results, WordPress throws away the previous results and runs another query on the database to bring back your results.
Because of this, it is generally recommended to hook into pre_get_posts instead. To do this you would create a function in your themeâs functions.php. Â This enables you to alter the query before it is run. However, this affects all of the queries on your site, front-end and admin, if youâre not careful. Â Therefore you need to put in checks to make sure itâs not an admin page/it is the main loop/it is in fact the template you wanted to affect.
In this example I have created a custom post type called âproductâ, and have a custom field called âcolourâ. My wordpress front page is set to âYour latest postsâ. WordPress will use the home.php template to disply this if it is available. Here I am altering the query for the home page to only show Products that are red:
function bb_red_things( $query ) { if ( is_home() ) { Â Â Â Â // Set post type to 'product' Â Â Â Â $query->set( 'post_type', 'product' ); Â Â Â Â // Limit to products with a custom field 'colour' set to 'red' $query->set( 'meta_key', 'colour'); $query->set( 'meta_value', 'red'); Â Â } } add_action( 'pre_get_posts', 'bb_red_things' );
Note that pre_get_posts doesnât work with Pages. Also, some template tags will not work (as theyâve not been set up yes at this point). For example, is_front_page() will not work, although is_home() will work. See the Codex on pre_get_posts for more details and examples.