WordPress query_posts and get_posts

The WordPress query_posts command allows you to query the WordPress wp_posts database and retrieve post objects (e.g. posts, pages, attachments) based on their attributes.

query_posts is used throughout the WordPress administration system, but it is most prominent in the WordPress Loop and underlies all of the WordPress Loop commands, e.g. the_post or the_title.

get_posts is similar to query_posts and is also used to query the wp_posts database. You will note however, that the argument list it uses is slightly different compared to query_posts, therefore make sure to refer to the WordPress codex to ensure that you are using the right argument names for each of these commands.

Both query_posts and get_posts are based on the WP_Query object. However, query_posts creates a global WP_Query object that is stored in the $wp_query global variable, whereas get_posts creates a local WP_Query object that only exists within the function.

The global $wp_query variable is later used by multiple functions within the WordPress Loop. That is why it is important NOT to use query_posts within an existing WordPress Loop because it will replace the existing Loop object (contained in $wp_query) with a new WP_Query object.

query_posts is most useful when you are writing a plugin, and want to display a list of post objects within a WordPress administration menu. In the administration area, there is no Loop to worry about.

When you are operating outside of the WordPress administration area (i.e. WordPress Dashboard), it is best to use the get_posts command so that you do not inadvertently corrupt your WordPress Loop.

Incidentally, if you want to use query_posts type attributes within a WordPress Loop, then you can just create your own local WP_Query object as follows –

    $tmp_query = new WP_Query;
    return $tmp_query->query($atts);

$atts should contain an attribute array similar to what you would use in the query_posts function. Here are the list of parameters for query_posts.

Here is another example –

    $tmp_query = new WP_Query;
    $tmp_result = $tmp_query->query('category_name=aciform');

How to Paginate Your query_posts Results

Sometimes, you may only want to show a certain fixed number of post objects per page, and allow users to browse through several pages of results. The code below will allow you to achieve this (partially extracted from the wp-admin/upload.php file).

	if (isset($_GET['paged'])) $cur_page = absint($_GET['paged']);
	else $cur_page = 1;

        // Get posts
	$args = array(
		'post_type' => 'attachment',
		'posts_per_page' => 5,
		'paged'=> $cur_page
        global $wp_query;
        $page_links_total =  $wp_query->max_num_pages;

        $page_links = paginate_links( array(
            'base' => add_query_arg( 'paged', '%#%' ),
            'format' => '',
            'prev_text' => __('&laquo;'),
            'next_text' => __('&raquo;'),
            'total' => $page_links_total,
            'current' => $cur_page
	if ( $page_links ) : 
	<div class="tablenav-pages">
		<?php $page_links_text = sprintf( '<span class="displaying-num">' . __( 'Displaying %s&#8211;%s of %s' ) . '</span>%s',
					number_format_i18n( ( $cur_page - 1 ) * $wp_query->query_vars['posts_per_page'] + 1 ),
					number_format_i18n( min( $cur_page * $wp_query->query_vars['posts_per_page'], $wp_query->found_posts ) ),
					number_format_i18n( $wp_query->found_posts ),
				); echo $page_links_text; 

Line 2 – The current page that the user is on is set as an address line argument ($_GET[‘paged’]) by the paginate_links function (line 16). The argument name ‘paged’ is set on line 17.

Line 9 – Make sure to include this page value while calling query_posts so that you will retrieve the right set of post objects for a given page.

Line 16 -Get the proper set of links for each page. Note that the paginate_links function is not dependent on any global variables (i.e. it is not dependent on $wp_query) so you can use it to generate page links for any list of objects by entering in proper values for total (total number of pages) and current (the current page).

Lines 27-35 -Display the page links returned by the paginate_links function.

Related Articles


  1. Frank says

    I wasn’t able to get any posts out of get_posts(), but your alternative $tmp_query solution worked, Thanks!

  2. Pratik says

    Great tutorial but can you just tell me how to paginate using get_post(), I am using $posts = get_posts($args); $posts->max_num_pages, $posts->post_count; both are returning null i want to use it inside next_posts_link($label,max_num_pages) function. Thanks in advance.

  3. says

    Totally agree with Daniel, thank you for taking the time to explain the difference between the variables and how/why/when they should be used 🙂

  4. says

    My spouse and I absolutely love your blog and find most of your post’s to be just what I’m looking for. can you offer guest writers to write content for you? I wouldn’t mind creating a post or elaborating on most of the subjects you write regarding here. Again, awesome web log!

    • ShibaShake says

      Thank you very much Daniel.

      Currently, I do not have my blog set up for multiple writers. This is definitely something that I will look into in the future.

  5. James Hobson says

    Had been looking for a way to get the number of pages for a while and came across it in your post.
    Many thanks

Leave a Reply

Your email address will not be published.