Codex tools: Log in
Languages: English • 日本語 • (Add your language)
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.
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.
(An ampersand (&) before a method name indicates it returns by reference.)
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.
<?php // The Query $the_query = new WP_Query( $args ); // The Loop while ( $the_query->have_posts() ) : $the_query->the_post(); echo '<li>'; the_title(); echo '</li>'; endwhile; // Reset Post Data wp_reset_postdata(); ?>
Show posts associated with certain author.
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' );
Show posts associated with certain categories.
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:
$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 ) ) );
Show posts associated with certain tags.
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.
Show posts associated with certain taxonomy.
Important Note: tax_query takes an array of tax query arguments arrays (it takes an array of arrays) - you can see this in the second example below. This construct allows you to query multiple taxonomies by using the relation parameter in the first (outer) array to describe the boolean relationship between the taxonomy queries.
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 );
Display content based on post and page parameters.
Show Post/Page by ID
Display post by ID:
$query = new WP_Query( 'p=7' );
Display page by ID:
$query = new WP_Query( 'page_id=7' );
Show Post/Page by Slug
Display post by slug:
$query = new WP_Query( 'name=about-my-life' );
Display page by 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 specific posts:
$query = new WP_Query( array( 'post_type' => 'page', 'post__in' => array( 2, 5, 12, 14, 20 ) ) );
Display all posts but NOT the specified 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.
Show posts associated with certain type or status.
Show Post by Type
Display only pages:
$query = new WP_Query( 'post_type=page' );
Display 'any' post type (retrieves any type except revisions and types with 'exclude_from_search' set to TRUE):
$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' ) ) );
Display all attachments:
$query = new WP_Query( array( 'post_status' => 'any', 'post_type' => 'attachment' ) );
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 WP_Query() remains the same.
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 ) );
Note: Setting offset parameter will ignore the paged parameter.
Sort retrieved posts.
Show Posts sorted by Title, Descending order
Display posts sorted by post title in a descending order:
$query = new WP_Query( array ( 'orderby' => 'title', 'order' => 'DESC' ) );
Show Random Post
Display one random post:
$query = new WP_Query( array ( 'orderby' => 'rand', 'posts_per_page' => '1' ) );
Show Popular Posts
Display posts ordered by comment count:
$query = new WP_Query( array( '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' ) );
Multiple 'orderby' values
Display pages ordered by 'title' and 'menu_order'. (title is dominant):
$query = new WP_Query( array( 'post_type' => 'page', 'orderby' => 'title menu_order', 'order' => 'ASC' ) );
Do you know how to sort the query if the meta_value is an array? Write it here :)
Show Sticky Posts or ignore them.
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( 'paged' ) ? get_query_var( 'paged' ) : 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 );
Show posts associated with a certain time period.
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 March 1 to March 15, 2010:
// 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 );
remove_filter( 'posts_where', 'filter_where' );
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 );
remove_filter( 'posts_where', 'filter_where' );
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 );
remove_filter( 'posts_where', 'filter_where' );
Show posts associated with a certain custom field.
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.
By using the 'meta_value' parameter the value 99 will be considered greater than 100 as the data are stored as 'strings', not 'numbers'. For number comparison use 'meta_value_num'.
$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' ) );
Single Custom Field Handling:
Display posts from a single custom field:
$args = array( 'post_type' => 'product', 'meta_query' => array( array( 'key' => 'color', 'value' => 'blue', 'compare' => 'NOT LIKE' ) ) ); $query = new WP_Query( $args );
(Note that meta_query expects nested arrays, even if you only have one query.)
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 );
Display posts that have meta key 'color' NOT LIKE value 'blue' OR meta key 'price' with values BETWEEN 20 and 100:
$args = array( 'post_type' => 'product', 'meta_query' => array( 'relation' => 'OR', array( 'key' => 'color', 'value' => 'blue', 'compare' => 'NOT LIKE' ), array( 'key' => 'price', 'value' => array( 20, 100 ), 'type' => 'numeric', 'compare' => 'BETWEEN' ) ) ); $query = new WP_Query( $args );
Display published posts, as well as private posts, if the user has the appropriate capability:
$query = new WP_Query( array( 'post_status' => array( 'publish', 'private' ), 'perm' => 'readable' ) );
In addition to the parameters mentioned above, you can also pass three different cache control flags: cache_results, update_post_term_cache, and update_post_meta_cache.
If you need to stop the data retrieved from being added to the cache you can pass cache_results as false (this is a master flag that will also turn off the other two), or you can be specific and pass update_post_term_cache and/or update_post_meta_cache depending on your requirements.
// Retrieve 50 posts, but don't add post meta to the cache $query = new WP_Query( array( 'posts_per_page' => 50, 'update_post_meta_cache' => false ) );
// Retrieve 50 posts, but don't add post information to the cache $query = new WP_Query( array( 'posts_per_page' => 50, 'cache_results' => false ) );
In general usage you should not need to use these - adding to the cache is the right thing to do - however they may be useful in specific circumstances.
An example of such circumstances might be when using a WP_Query to retrieve a list of post titles and URLs to be displayed, but in which no other information about the post will be used and the taxonomy and meta data won't be needed. By not loading this information, you can save time from the extra unnecessary SQL queries.
Note: If a persistent object cache backend (such as memcached) is used, these flags are set to false by default since there is no need to update the cache every page load when a persistent cache exists.
Note, that there are more filters than the mentioned. As it is hard to keep the codex up to date, please inspect the get_posts(); function inside the WP_Query class yourself (/wp-includes/query.php).
WP_Query() is located in wp-includes/query.php.
Query Tags: WP_Query (Class), get_query_var(), query_posts(), have posts(), the_post(), rewind_posts(), wp_reset_postdata(), wp_reset_query()