Wednesday, December 17, 2014

How to Fetch Posts in WordPress



As WordPress theme or plugin developers, you could come across a need to retrieve a collection of posts, to be displayed on a page. As a simple use case consider a requirement to display the latest 5 posts on your homepage, or to list posts for a particular category, in a category archive page.

For this, WordPress presents you with several options. You could use the WP_query class, the get_posts function or the query_posts function (it’s important to note right in the beginning that the query_posts function comes with a warning).

Put very simply, the main purpose of any of these is to retrieve a set of posts. But the method used by each is different. So how are you to decide which method you should be using? Let’s find out.

A Crash Course on WordPress Basics: The Post Object and Loop

For those of you new to WordPress let’s understand some basics.

The Post Object

A post contains not only written content, but consists of several other parameters like the title, the id, the category, etc (as part of the post object). Apart from this information, every post is linked to additional data like author information, the comments, and other meta data information (not part of the post object).

The Loop

The Loop is the main function used by WordPress to display posts. The details of the post to be displayed, will be maintained for every post within the loop. This is a very important function and should not be meddled with, without knowledge of the core operations.

Okay basics done, coming back to our main topic; how to fetch posts in WordPress.

Understanding the use of WP_query, get_posts, query_posts

Since we have three options, let’s look at each in a bit more detail.

WP_query Class

Both get_posts and query_posts use the instance of WP_query class.

WP_query class provides you with a global instance $wp_query which is the main query. When a request is made to display posts (for example this could be from the theme to display the archive page) the $wp_query is populated with the query data (which would contain the query conditions, url arguments, etc.). It then fetches the required posts, and the main loop uses the $wp_query instance to display the posts and post data.

In case you wanted to display additional information, say for example a related posts section above the footer,  it is best not to alter the main loop. Instead, you would have to create a secondary loop, by creating a new instance of the WP_query class and using this instance to perform the needed operations.

For this, the WP_query class provides several methods and properties to loop through the posts. It is advisable not to change the properties directly but use the methods provided to perform the needed action.

// Create the query
$custom_query = new WP_Query($args);

if( $custom_query->have_posts() ){
    while( $custom_query->have_posts() ){

        // set the $post to indicate the current post

        $custom_query->the_post();

       // do some operation
    }
}

// important to reset $post
wp_reset_postdata();

Note the use of wp_reset_postdata function at the end. This is very important to reset the global $post variable which is updated in the loop.

get_posts Function

The get_posts function is essentially a wrapper over the create new instance of WP_query but returns an array of posts (not a query object).

query_posts Function

Finally the query_posts function retrieves posts, but should not be used because it alters the main loop to return the needed results.

pre_get_posts Function

In case you want to add a condition before the main loop is executed use must use the pre_get_posts hook provided by WordPress to add the condition.

For example if you wanted to display 5 posts on a page:

function wdm_query_condition( $query ) {
    // considering wdm-page is the page slug
    if ( $query->is_page('wdm-page') && $query->is_main_query() ) {
        $query->set( 'posts_per_page', 5 );
    }
}

// add the condition in pre_get_posts
add_action( 'pre_get_posts', 'wdm_query_condition' );

You only need to remember two options; the use of WP_query and the pre_get_posts function. Remember to use WP_query to add custom loops or secondary loops, and pre_get_posts function, to alter the main loop.