WordPress.org

Ready to get started?Download WordPress

Codex

Attention Interested in functions, hooks, classes, or methods? Check out the new WordPress Code Reference!

Class Reference/WP Query

Role of WP_Query

WP_Query is a class defined in wp-includes/query.php that deals with the intricacies of a request to a WordPress blog. The wp-blog-header.php (or the WP class in Version 2.0) gives the $wp_query object information defining the current request, and then $wp_query determines what type of query it's dealing with (possibly a category archive, dated archive, feed, or search), and fetches the requested posts. It retains a lot of information on the request, which can be pulled at a later date.

Methods and Properties

This is the formal documentation of WP_Query. You shouldn't alter the properties directly, but instead use the methods to interact with them. Also see Interacting with WP_Query for some useful functions that avoid the need to mess around with class internals and global variables.

Properties

$query
Holds the query string that was passed to the $wp_query object by wp-blog-header.php (or the WP class in Version 2.0). For information on the construction of this query string (in WP1.5 with wp-blog-header.php - the following link is fairly outdated now), see WordPress Code Flow.
$query_vars
An associative array containing the dissected $query: an array of the query variables and their respective values.
$queried_object
Applicable if the request is a category, author, permalink or Page. Holds information on the requested category, author, post or Page.
$queried_object_id
If the request is a category, author, permalink or page, holds the corresponding ID.
$posts
Gets filled with the requested posts from the database.
$post_count
The number of posts being displayed.
$current_post
(available during The Loop) Index of the post currently being displayed.
$post
(available during The Loop) The post currently being displayed.
$is_single, $is_page, $is_archive, $is_preview, $is_date, $is_year, $is_month, $is_time, $is_author, $is_category, $is_tag, $is_tax, $is_search, $is_feed, $is_comment_feed, $is_trackback, $is_home, $is_404, $is_comments_popup, $is_admin, $is_attachment, $is_singular, $is_robots, $is_posts_page, $is_paged
Booleans dictating what type of request this is. For example, the first three represent 'is it a permalink?', 'is it a Page?', 'is it any type of archive page?', respectively.

Methods

(An ampersand (&) before a method name indicates it returns by reference.)

init()
Initialise the object, set all properties to null, zero or false.
parse_query($query)
Takes a query string defining the request, parses it and populates all properties apart from $posts, $post_count, $post and $current_post.
parse_query_vars()
Reparse the old query string.
get($query_var)
Get a named query variable.
set($query_var, $value)
Set a named query variable to a specific value.
&get_posts()
Fetch and return the requested posts from the database. Also populate $posts and $post_count.
next_post()
(to be used when in The Loop) Advance onto the next post in $posts. Increment $current_post and set $post.
the_post()
(to be used when in The Loop) Advance onto the next post, and set the global $post variable.
have_posts()
(to be used when in The Loop, or just before The Loop) Determine if we have posts remaining to be displayed.
rewind_posts()
Reset $current_post and $post.
&query($query)
Call parse_query() and get_posts(). Return the results of get_posts().
get_queried_object()
Set $queried_object if it's not already set and return it.
get_queried_object_id()
Set $queried_object_id if it's not already set and return it.
WP_Query($query = '') (constructor)
If you provide a query string, call query() with it.

Interacting with WP_Query

Most of the time you can find the information you want without actually dealing with the class internals and globals variables. There are a whole bunch of functions that you can call from anywhere that will enable you to get the information you need.

There are two main scenarios you might want to use WP_Query in. The first is to find out what type of request WordPress is currently dealing with. The $is_* properties are designed to hold this information: use the Conditional Tags to interact here. This is the more common scenario to plugin writers (the second normally applies to theme writers).

The second is during The Loop. WP_Query provides numerous functions for common tasks within The Loop. To begin with, have_posts(), which calls $wp_query->have_posts(), is called to see if there are any posts to show. If there are, a while loop is begun, using have_posts() as the condition. This will iterate around as long as there are posts to show. In each iteration, the_post(), which calls $wp_query->the_post() is called, setting up internal variables within $wp_query and the global $post variable (which the Template Tags rely on), as above. These are the functions you should use when writing a theme file that needs a loop. See also The Loop and The Loop in Action for more information.

Note: If you use the_post() with your query, you need to run wp_reset_postdata() afterwards to have Template Tags use the main query's current post again.

Example

Using WP_Query to retrieve only pages given in a specific array

<?php
$args = array(
	'post_type' => 'page',
	'post__in'  => array( '595', '33', 44 )
);
$the_query = new WP_Query( $args );
?>

Parameters

Author Parameters

Show posts associated with certain author.

  • author (int) - use author id.
  • author_name (string) - use 'user_nicename' (NOT name).

Show Posts for one Author

Display posts by author, using author id:

$query = new WP_Query( 'author=123' );

Display posts by author, using author 'user_nicename':

$query = new WP_Query( 'author_name=rami' );

Show Posts From Several Authors

Display posts from several specific authors:

$query = new WP_Query( 'author=2,6,17,38' );

Exclude Posts Belonging to an Author

Display all posts except those from an author by prefixing its id with a '-' (minus) sign:

$query = new WP_Query( 'author=-12,-34,-56' );

Category Parameters

Show posts associated with certain categories.

  • cat (int) - use category id.
  • category_name (string) - use category slug (NOT name).
  • category__and (array) - use category id.
  • category__in (array) - use category id.
  • category__not_in (array) - use category id.

Show Posts for One Category

Display posts that have this category (and any children of that category), using category id:

$query = new WP_Query( 'cat=4' );

Display posts that have this category (and any children of that category), using category slug:

$query = new WP_Query( 'category_name=staff' );

Show Posts From Several Categories

Display posts that have these categories, using category id:

$query = new WP_Query( 'cat=2,6,17,38' );

Display posts that have these categories, using category slug (not possible with wp3.0):

$query = new WP_Query( 'category_name=staff,news' );

Exclude Posts Belonging to Category

Display all posts except those from a category by prefixing its id with a '-' (minus) sign.

$query = new WP_Query( 'cat=-12,-34,-56' );

Multiple Category Handling

Display posts that are in multiple categories. This shows posts that are in both categories 2 and 6:

$query = new WP_Query( array( 'category__and' => array( 2, 6 ) ) );

To display posts from either category 2 OR 6, you could use cat as mentioned above, or by using category__in (note this does not show posts from any children of these categories):

$query = new WP_Query( array( 'category__in' => array( 2, 6 ) ) );

You can also exclude multiple categories this way:

$query = new WP_Query( array( 'category__not_in' => array( 2, 6 ) ) );

Tag Parameters

Show posts associated with certain tags.

  • tag (string) - use tag slug.
  • tag_id (int) - use tag id.
  • tag__and (array) - use tag ids.
  • tag__in (array) - use tag ids.
  • tag__not_in (array) - use tag ids.
  • tag_slug__and (array) - use tag slugs.
  • tag_slug__in (array) - use tag slugs.

Show Posts for One Tag

Display posts that have this tag, using tag slug:

$query = new WP_Query( 'tag=cooking' );

Display posts that have this tag, using tag id:

$query = new WP_Query( 'tag_id=13' );

Show Posts From Several Tags

Display posts that have "either" of these tags:

$query = new WP_Query( 'tag=bread,baking' );

Display posts that have "all" of these tags:

$query = new WP_Query( 'tag=bread+baking+recipe' );

Multiple Tag Handling

Display posts that are tagged with both tag id 37 and tag id 47:

$query = new WP_Query( array( 'tag__and' => array( 37, 47 ) ) );

To display posts from either tag id 37 or 47, you could use tag as mentioned above, or explicitly specify by using tag__in:

$query = new WP_Query( array( 'tag__in' => array( 37, 47 ) ) );

Display posts that do not have any of the two tag ids 37 and 47:

$query = new WP_Query( array( 'tag__not_in' => array( 37, 47 ) ) );

The tag_slug__in and tag_slug__and behave much the same, except match against the tag's slug.

Taxonomy Parameters

Show posts associated with certain taxonomy.

  • {tax} (string) - use taxonomy slug. Deprecated as of Version 3.1 in favor of 'tax_query'.
  • tax_query (array) - use taxonomy parameters (available with Version 3.1).
    • taxonomy (string) - Taxonomy.
    • field (string) - Select taxonomy term by ('id' or 'slug')
    • terms (int/string/array) - Taxonomy term(s).
    • operator (string) - Operator to test. Possible values are 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'.

Simple Taxonomy Query:

Display posts tagged with 'bob', under 'people' custom taxonomy:

$query = new WP_Query( array( 'people' => 'bob' ) );

Display posts tagged with 'bob', under 'people' custom taxonomy, using 'tax_query':

$args = array(
	'tax_query' => array(
		array(
			'taxonomy' => 'people',
			'field' => 'slug',
			'terms' => 'bob'
		)
	)
);
$query = new WP_Query( $args );

Multiple Taxonomy Handling:

Display posts from several custom taxonomies:

$query = new WP_Query( array( 'people' => 'bob', 'language' => 'english' ) );

Display posts from several custom taxonomies, using 'tax_query':

$args = array(
	'tax_query' => array(
		'relation' => 'AND',
		array(
			'taxonomy' => 'movie_janner',
			'field' => 'slug',
			'terms' => array( 'action', 'commedy' ),
		),
		array(
			'taxonomy' => 'actor',
			'field' => 'id',
			'terms' => array( 103, 115, 206 ),
			'operator' => 'NOT IN',
		)
	)
)
$query = new WP_Query( $args );

Display posts that are in the 'quotes' category OR have the 'quote' format:

$args = array(
	'tax_query' => array(
		'relation' => 'OR',
		array(
			'taxonomy' => 'category',
			'field' => 'slug',
			'terms' => array( 'quotes' ),
		),
		array(
			'taxonomy' => 'post-format',
			'field' => 'slug',
			'terms' => array( 'post-format-quote' )
		)
	)
)
$query = new WP_Query( $args );

Post & Page Parameters

Show posts associated with posts and pages.

  • p (int) - use post id.
  • name (string) - use post slug.
  • page_id (int) - use page id.
  • pagename (string) - use page slug.
  • post_parent (int) - use page id. Return just the child Pages.
  • post__in (array) - use post ids. Specify posts to retrieve.
  • post__not_in (array) - use post ids. Specify post NOT to retrieve.

Show Post/Page by ID

Display post by his ID:

$query = new WP_Query( 'p=7' );

Display page by his ID:

$query = new WP_Query( 'page=7' );

Show Post/Page by Slug

Display post by his slug:

$query = new WP_Query( 'name=about-my-life' );

Display page by his slug:

$query = new WP_Query( 'pagename=contact' );

Show Child Posts/Pages

Display child page using the slug of the parent and the child page, separated by a slash (e.g. 'parent_slug/child_slug'):

$query = new WP_Query( 'pagename=contact_us/canada' );

Display child pages using parent page ID:

$query = new WP_Query( 'post_parent=93' );

Multiple Posts/Pages Handling

Display only the specify posts:

$query = new WP_Query( array( 'post__in' => array( 2, 5, 12, 14, 20 ) ) );

Display all posts but NOT the specify ones:

$query = new WP_Query( array( 'post__not_in' => array( 2, 5, 12, 14, 20 ) ) );

Note: you cannot combine 'post__in' and 'post__not_in' in the same query.

Type & Status Parameters

Show posts associated with certain type or status.

  • post_type (string / array) - use post types. Retrieves posts by Post Types, default value is 'post';
    • 'post'
    • 'page'
    • 'revision'
    • 'attachment'
    • 'any' - retrieves any type except revisions
    • Custom Post Types (e.g. movies)
  • post_status (string / array) - use post status. Retrieves posts by Post Status, default value is 'publish';
    • 'publish' - a published post or page
    • 'pending' - post is pending review
    • 'draft' - a post in draft status
    • 'auto-draft' - a newly created post, with no content
    • 'future' - a post to publish in the future
    • 'private' - not visible to users who are not logged in
    • 'inherit' - a revision. see get_children.
    • 'trash' - post is in trashbin. added with Version 2.9.

Show Post by Type

Display only pages:

$query = new WP_Query( 'post_type=page' );

Display 'any' post type (retrieves any type except revisions):

$query = new WP_Query( 'post_type=any' );

Display multiple post types, including custom post types:

$query = new WP_Query( array( 'post_type' => array( 'post', 'page', 'movie', 'book' ) ) );

Show Post by Status

Display only drafts:

$query = new WP_Query( 'post_status=draft' );

Display multiple post status:

$query = new WP_Query( array( 'post_status' => array( 'pending', 'draft', 'future' ) ) );

Pagination Parameters

  • showposts (int) - number of post to show per page. Deprecated as of Version 2.1 in favor of 'posts_per_page'.
  • posts_per_page (int) - number of post to show per page (available with Version 2.1). Use 'posts_per_page'=>-1 to show all posts. Note if the query is in a feed, wordpress overwrites this parameter with the stored 'posts_per_rss' option. To reimpose the limit, try using the 'post_limits' filter.
  • nopaging (bool) - show all posts or use pagination. Default value is 'false', use paging.
  • paged (int) - number of page. Show the posts that would normally show up just on page X when using the "Older Entries" link.

Show x Posts per page

Display 3 posts per page:

$query = new WP_Query( 'posts_per_page=3' );

Show All Post

Display all posts in one page:

$query = new WP_Query( 'posts_per_page=-1' );

Display all posts by disabling pagination:

$query = new WP_Query( 'nopaging=true' );

Show Posts from page x

Display posts from page number 6:

$query = new WP_Query( 'paged=6' );

Show Posts from Current Page

Display posts from current page:

$query = new WP_Query( 'paged=' . get_query_var( 'page' ) );

Pagination Note: You should set get_query_var( 'page' ); if you want your query to work with pagination. Since Wordpress 3.0.2, you do get_query_var( 'page' ) instead of get_query_var( 'paged' ). The pagination parameter 'paged' for query_posts() remains the same.

Offset Parameter

  • offset (int) - number of post to displace or pass over.

Pass over 3 Posts

Display posts from the 4th one:

$query = new WP_Query( 'offset=3' ) );

Show 5 Posts starting from the second one

Display 5 posts per page which follow the most recent (1):

$query = new WP_Query( array( 'posts_per_page' => 5, 'offset' => 1 ) );

Order & Orderby Parameters

Sort retrieved posts.

  • order (string) - Designates the ascending or descending order of the 'orderby' parameter.
    • 'ASC' - ascending order from lowest to highest values (1, 2, 3; a, b, c).
    • 'DESC' - descending order from highest to lowest values (3, 2, 1; c, b, a).
  • orderby (string) - Sort retrieved posts by:
    • 'none' - No order (available with Version 2.8).
    • 'id' - Order by post id.
    • 'author' - Order by author.
    • 'title' - Order by title.
    • 'date' - Order by date. (default, if not set to none)
    • 'modified' - Order by last modified date.
    • 'parent' - Order by post/page parent id.
    • 'rand' - Random order.
    • 'comment_count' - Order by number of comments (available with Version 2.9).
    • 'menu_order' - Order by Page Order. Used most often for Pages (Order field in the Edit Page Attributes box) and for attachments (the integer fields in the Insert / Upload Media Gallery dialog), but could be used for any post type with distinct 'menu_order' values (they all default to 0).
    • 'meta_value' - Note that a 'meta_key=keyname' must also be present in the query. Note also that the sorting will be alphabetical which is fine for strings (i.e. words), but can be unexpected for numbers (e.g. 1, 3, 34, 4, 56, 6, etc, rather than 1, 3, 4, 6, 34, 56 as you might naturally expect).
    • 'meta_value_num' - Order by numeric meta value (available with Version 2.8). Also note that a 'meta_key=keyname' must also be present in the query. This value allows for numerical sorting as noted above in 'meta_value'.

Show Posts sorted by Title, Descending order

Display posts sorted by post title in a descending order:

$query = new WP_Query( 'orderby=title&order=DESC' );

Show Random Post

Display one random post:

$query = new WP_Query( 'orderby=rand&posts_per_page=1' );

Show Popular Posts

Display posts ordered by comment count:

$query = new WP_Query( 'orderby=comment_count' );

Show Products sorted by Price

Display posts with 'Product' type ordered by 'Price' custom field:

$query = new WP_Query( array ( 'post_type' => 'product', 'orderby' => 'meta_value', 'meta_key' => 'price' ) );

Note, that there can be more than one orderby value.

Display 'page' post type ordered by 'title' and 'menu_order'. (Separated with spaces to work properly.)

$query = new WP_Query( 'post_type=page&orderby=title menu_order&order=ASC' );

Sticky Post Parameters

Show Sticky Posts or ignore them.

  • caller_get_posts (bool) - ignore sticky posts or not. Deprecated as of Version 3.1 in favor of 'ignore_sticky_posts'.
  • ignore_sticky_posts (bool) - ignore sticky posts or not. Default value is 0, don't ignore. Ignore/exclude sticky posts being included at the beginning of posts returned, but the sticky post will still be returned in the natural order of that list of posts returned.

Show Sticky Posts

Display just the first sticky post:

$sticky = get_option( 'sticky_posts' );
$query = new WP_Query( 'p=' . $sticky[0] );

Display just the first sticky post, if none return the last post published:

$args = array(
	'posts_per_page' => 1,
	'post__in'  => get_option( 'sticky_posts' ),
	'ignore_sticky_posts' => 1
);
$query = new WP_Query( $args );

Display just the first sticky post, if none return nothing:

$sticky = get_option( 'sticky_posts' );
$args = array(
	'posts_per_page' => 1,
	'post__in'  => $sticky,
	'ignore_sticky_posts' => 1
);
$query = new WP_Query( $args );
if ( $sticky[0] ) {
	// insert here your stuff...
}

Don't Show Sticky Posts

Exclude all sticky posts from the query:

$query = new WP_Query( array( 'post__not_in' => get_option( 'sticky_posts' ) ) );

Exclude sticky posts from a category. Return ALL posts within the category, but don't show sticky posts at the top. The 'sticky posts' will still show in their natural position (e.g. by date):

$query = new WP_Query( 'ignore_sticky_posts=1&posts_per_page=3&cat=6' );

Exclude sticky posts from a category. Return posts within the category, but exclude sticky posts completely, and adhere to paging rules:

$paged = get_query_var( 'page' ) ? get_query_var( 'page' ) : 1;
$sticky = get_option( 'sticky_posts' );
$args = array(
	'cat' => 3,
	'ignore_sticky_posts' => 1,
	'post__not_in' => $sticky,
	'paged' => $paged
);
$query = new WP_Query( $args );

Time Parameters

Show posts associated with a certain time period.

  • year (int) - 4 digit year (e.g. 2011).
  • monthnum (int) - Month number (from 1 to 12).
  • w (int) - Week of the year (from 0 to 53). Uses the MySQL WEEK command Mode=1.
  • day (int) - Day of the month (from 1 to 31).
  • hour (int) - Hour (from 0 to 23).
  • minute (int) - Minute (from 0 to 60).
  • second (int) - Second (0 to 60).

Returns posts for just the current date:

$today = getdate();
$query = new WP_Query( 'year=' . $today["year"] . '&monthnum=' . $today["mon"] . '&day=' . $today["mday"] );

Returns posts for just the current week:

$week = date('W');
$year = date('Y');
$query = new WP_Query( 'year=' . $year . '&w=' . $week );

Returns posts dated December 20:

$query = new WP_Query( 'monthnum=12&day=20' );

Note: The queries above return posts for a specific date period in history, i.e. "Posts from X year, X month, X day". They are unable to fetch posts from a timespan relative to the present, so queries like "Posts from the last 30 days" or "Posts from the last year" are not possible with a basic query, and require use of the posts_where filter to be completed. The examples below use the posts_where filter, and should be modifyable for most time-relative queries.

Return posts for posts for March 1 to March 15, 2009:

// Create a new filtering function that will add our where clause to the query
function filter_where( $where = '' ) {
	// posts for March 1 to March 15, 2010
	$where .= " AND post_date >= '2010-03-01' AND post_date < '2010-03-16'";
	return $where;
}
add_filter( 'posts_where', 'filter_where' );

$query = new WP_Query( $query_string );

Return posts from the last 30 days:

// Create a new filtering function that will add our where clause to the query
function filter_where( $where = '' ) {
	// posts in the last 30 days
	$where .= " AND post_date > '" . date('Y-m-d', strtotime('-30 days')) . "'";
	return $where;
}
add_filter( 'posts_where', 'filter_where' );

$query = new WP_Query( $query_string );

Return posts 30 to 60 days old

// Create a new filtering function that will add our where clause to the query
function filter_where( $where = '' ) {
	// posts  30 to 60 days old
	$where .= " AND post_date >= '" . date('Y-m-d', strtotime('-60 days')) . "'" . " AND post_date <= '" . date('Y-m-d', strtotime('-30 days')) . "'";
	return $where;
}
add_filter( 'posts_where', 'filter_where' );

$query = new WP_Query( $query_string );

Custom Field Parameters

Show posts associated with a certain custom field.

  • meta_key (string) - Custom field key. Deprecated as of Version 3.1 in favor of 'meta_query'.
  • meta_value (string) - Custom field value. Deprecated as of Version 3.1 in favor of 'meta_query'.
  • meta_compare (string) - Operator to test the 'meta_value'. Possible values are '!=', '>', '>=', '<', or '<='. Default value is '='. Deprecated as of Version 3.1 in favor of 'meta_query'.
  • meta_query (array) - Custom field parameters (available with Version 3.1).
    • key (string) - Custom field key.
    • value (string) - Custom field value.
    • compare (string) - Operator to test. Possible values are '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. Default value is '='.
    • type (string) - Custom field type. Possible values are 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'. Default value is 'CHAR'.

Simple Custom Field Query:

Display posts where the custom field key is 'color', regardless of the custom field value:

$query = new WP_Query( 'meta_key=color' );

Display posts where the custom field value is 'blue', regardless of the custom field key:

$query = new WP_Query( 'meta_value=blue' );

Display Page where the custom field value is 'blue', regardless of the custom field key:

$query = new WP_Query( 'meta_value=blue&post_type=page' );

Display posts where the custom field key is 'color' and the custom field value is 'blue':

$query = new WP_Query( array( 'meta_key' => 'color', 'meta_value' => 'blue' ) );

Display posts where the custom field key is 'color' and the custom field value IS NOT 'blue':

$query = new WP_Query( array( 'meta_key' => 'color', 'meta_value' => 'blue', 'meta_compare' => '!=' ) );

Display 'product'(s) where the custom field key is 'price' and the custom field value that is LESS THAN OR EQUAL TO 22. Note the value 99 will be considered greater than 100 as the data is stored as 'strings', not 'numbers'.

$query = new WP_Query( array( 'meta_key' => 'price', 'meta_value' => '22', 'meta_compare' => '<=', 'post_type' => 'product' ) );

Display posts with a custom field value of zero (0), regardless of the custom field key:

$query = new WP_Query( array ( 'meta_value' => '_wp_zero_value' ) );

Multiple Custom Field Handling:

Display posts from several custom field:

$args = array(
	'post_type' => 'product',
	'meta_query' => array(
		array(
			'key' => 'color',
			'value' => 'blue',
			'compare' => 'NOT LIKE'
		),
		array(
			'key' => 'price',
			'value' => array( 20, 100 ),
			'type' => 'numeric',
			'compare' => 'BETWEEN'
		)
	)
 );
$query = new WP_Query( $args );

Filters

  • posts_distinct - Alters SQL 'DISTINCTROW' clause to the query that returns the post array.
  • posts_groupby - Alters SQL 'GROUP BY' clause of the query that returns the post array.
  • posts_join - Alters SQL 'JOIN' clause of the query that returns the post array.
  • post_limits - Alters SQL 'LIMIT' clause of the query that returns the post array.
  • posts_orderby - Alters SQL 'ORDER BY' clause of the query that returns the post array.
  • posts_where - Alters SQL 'WHERE' clause of the query that returns the post array.
  • posts_join_paged - Alters SQL paging for posts using 'JOIN' clause of the query that returns the post array.
  • posts_where_paged - Alters SQL paging for posts using 'WHERE' clause of the query that returns the post array.

Source File

WP_Query() is located in wp-includes/query.php.

See also index of Function Reference and index of Template Tags.