WP_Query Class
The main WordPress query class. Handles post retrieval, The Loop, and query state.
Source: wp-includes/class-wp-query.php
Since: 1.5.0
Basic Usage
$query = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 10,
'category_name' => 'news',
) );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
the_title();
the_content();
}
wp_reset_postdata();
}Properties
Query State
| Property | Type | Description |
|---|---|---|
$query | array | Original query vars as passed |
$query_vars | array | Parsed and filled query vars |
$request | string | SQL query string |
Results
| Property | Type | Description |
|---|---|---|
$posts | `WP_Post[] | int[]` |
$post | `WP_Post | null` |
$post_count | int | Number of posts in current page |
$found_posts | int | Total matching posts (all pages) |
$max_num_pages | int | Number of pages |
$current_post | int | Index of current post (-1 before loop) |
Queried Object
| Property | Type | Description |
|---|---|---|
$queried_object | `WP_Term | WP_Post_Type |
$queried_object_id | int | ID of queried object |
Loop State
| Property | Type | Description |
|---|---|---|
$in_the_loop | bool | Whether currently in the loop |
$before_loop | bool | Whether before the loop has started (since 6.3.0) |
Query Type Flags
| Property | Description |
|---|---|
$is_single | Single post (not page or attachment) |
$is_page | Single page |
$is_attachment | Single attachment |
$is_singular | Any single post/page/attachment |
$is_preview | Post preview |
$is_archive | Any archive page |
$is_category | Category archive |
$is_tag | Tag archive |
$is_tax | Custom taxonomy archive |
$is_author | Author archive |
$is_date | Any date archive |
$is_year | Year archive |
$is_month | Month archive |
$is_day | Day archive |
$is_time | Time archive |
$is_post_type_archive | Post type archive |
$is_home | Blog home (posts page) |
$is_front_page() | Site front page (method, not property) |
$is_privacy_policy | Privacy policy page |
$is_search | Search results |
$is_feed | Feed request |
$is_comment_feed | Comments feed |
$is_trackback | Trackback endpoint |
$is_paged | Paginated (page 2+) |
$is_admin | Admin request |
$is_404 | No results found |
$is_embed | Embedded post |
$is_robots | robots.txt request |
$is_favicon | favicon.ico request |
$is_posts_page | Page assigned as posts page |
Sub-Query Objects
| Property | Type | Description |
|---|---|---|
$tax_query | `WP_Tax_Query | null` |
$meta_query | `WP_Meta_Query | false` |
$date_query | `WP_Date_Query | false` |
Comments
| Property | Type | Description |
|---|---|---|
$comments | WP_Comment[] | Comments for current post |
$comment | WP_Comment | Current comment in loop |
$comment_count | int | Number of comments |
$current_comment | int | Current comment index |
$max_num_comment_pages | int | Number of comment pages |
Query Variables Reference
Post Selection
By ID
| Variable | Type | Description |
|---|---|---|
p | int | Post ID |
post__in | int[] | Array of post IDs to include |
post__not_in | int[] | Array of post IDs to exclude |
page_id | int | Page ID |
// Single post by ID
'p' => 42
// Multiple specific posts
'post__in' => array( 1, 2, 3 )
// Exclude posts
'post__not_in' => array( 10, 20 )By Slug/Name
| Variable | Type | Description |
|---|---|---|
name | string | Post slug |
pagename | string | Page slug (supports hierarchy: parent/child) |
post_name__in | string[] | Array of post slugs |
title | string | Exact post title match |
// By slug
'name' => 'hello-world'
// By page path
'pagename' => 'about/team'
// Multiple slugs
'post_name__in' => array( 'hello', 'world' )Post Type & Status
| Variable | Type | Description |
|---|---|---|
post_type | `string | string[]` |
post_status | `string | string[]` |
Post Type Values:
'post'— Blog posts'page'— Pages'attachment'— Media'revision'— Revisions'nav_menu_item'— Menu items'any'— All types except revisions and types withexclude_from_search = true- Custom post type slugs
Post Status Values:
'publish'— Published'pending'— Pending review'draft'— Draft'auto-draft'— Auto-draft'future'— Scheduled'private'— Private'inherit'— Inherits parent (attachments)'trash'— Trashed'any'— All excepttrashandauto-draft
// Multiple post types
'post_type' => array( 'post', 'page', 'product' )
// Multiple statuses
'post_status' => array( 'publish', 'private' )Pagination
| Variable | Type | Description |
|---|---|---|
posts_per_page | int | Posts per page. -1 for all. |
posts_per_archive_page | int | Posts per page on archives |
nopaging | bool | Disable pagination |
paged | int | Page number |
offset | int | Number of posts to skip |
page | int | Page number for static front page |
// 10 posts per page, page 2
'posts_per_page' => 10,
'paged' => 2
// Skip first 5 posts
'offset' => 5
// All posts, no pagination
'posts_per_page' => -1
// or
'nopaging' => trueCategory Parameters
| Variable | Type | Description |
|---|---|---|
cat | `int | string` |
category_name | string | Category slug (includes children) |
category__in | int[] | Category IDs (no children) |
category__not_in | int[] | Exclude category IDs |
category__and | int[] | Posts in ALL listed categories |
// By category ID
'cat' => 5
// Multiple categories (OR)
'cat' => '2,6,17'
// Exclude category
'cat' => '-12'
// By slug
'category_name' => 'news'
// Posts in ALL categories
'category__and' => array( 2, 6 )
// Posts in ANY category (no children)
'category__in' => array( 2, 6 )Tag Parameters
| Variable | Type | Description |
|---|---|---|
tag | string | Tag slug(s). Comma = OR, plus = AND |
tag_id | int | Tag ID |
tag__in | int[] | Tag IDs (OR) |
tag__not_in | int[] | Exclude tag IDs |
tag__and | int[] | Posts with ALL tags |
tag_slug__in | string[] | Tag slugs (OR) |
tag_slug__and | string[] | Tag slugs (AND) |
// Single tag
'tag' => 'bread'
// Multiple tags (OR)
'tag' => 'bread,butter'
// Multiple tags (AND)
'tag' => 'bread+butter'
// By tag IDs
'tag__in' => array( 37, 47 )
// All tags required
'tag__and' => array( 37, 47 )Taxonomy Parameters (tax_query)
| Variable | Type | Description |
|---|---|---|
tax_query | array | Complex taxonomy query |
tax_query Structure:
'tax_query' => array(
'relation' => 'AND', // 'AND' or 'OR' between clauses
array(
'taxonomy' => 'genre', // Taxonomy name
'field' => 'slug', // 'term_id', 'slug', 'name', or 'term_taxonomy_id'
'terms' => array( 'action', 'comedy' ),
'operator' => 'IN', // 'IN', 'NOT IN', 'AND', 'EXISTS', 'NOT EXISTS'
'include_children' => true, // Include children terms
),
array(
'taxonomy' => 'actor',
'field' => 'term_id',
'terms' => array( 103, 115 ),
),
)Operators:
'IN'— Match any term (default)'NOT IN'— Exclude posts with these terms'AND'— Match ALL terms'EXISTS'— Has any term in taxonomy'NOT EXISTS'— Has no terms in taxonomy
Author Parameters
| Variable | Type | Description |
|---|---|---|
author | `int | string` |
author_name | string | Author nicename (slug) |
author__in | int[] | Author IDs to include |
author__not_in | int[] | Author IDs to exclude |
// By author ID
'author' => 1
// Multiple authors
'author' => '1,2,3'
// Exclude author
'author' => '-1'
// By nicename
'author_name' => 'john-doe'
// Multiple authors
'author__in' => array( 1, 5, 12 )Date Parameters
| Variable | Type | Description |
|---|---|---|
year | int | Four-digit year |
monthnum | int | Month (1-12) |
day | int | Day of month (1-31) |
w | int | Week of year (0-53) |
hour | int | Hour (0-23) |
minute | int | Minute (0-59) |
second | int | Second (0-59) |
m | int | YearMonth (e.g., 202301) |
date_query | array | Complex date query |
// Posts from January 2023
'year' => 2023,
'monthnum' => 1
// Combined format
'm' => 202301
// Complex date query
'date_query' => array(
array(
'after' => 'January 1st, 2023',
'before' => 'December 31st, 2023',
'inclusive' => true,
),
)See class-wp-date-query.md for complete date_query documentation.
Meta (Custom Field) Parameters
| Variable | Type | Description |
|---|---|---|
meta_key | string | Custom field key |
meta_value | string | Custom field value |
meta_compare | string | Comparison operator |
meta_type | string | Data type for CAST |
meta_query | array | Complex meta query |
Simple Meta Query:
// Posts with specific meta value
'meta_key' => 'color',
'meta_value' => 'blue'
// Numeric comparison
'meta_key' => 'price',
'meta_value' => 100,
'meta_compare' => '>=',
'meta_type' => 'NUMERIC'Complex meta_query:
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'color',
'value' => 'blue',
'compare' => '=',
),
'price_clause' => array( // Named clause for ordering
'key' => 'price',
'value' => array( 20, 100 ),
'type' => 'NUMERIC',
'compare' => 'BETWEEN',
),
),
'orderby' => 'price_clause' // Order by named clauseCompare Operators:
'=','!='— Equal, not equal'>','>=','<','<='— Numeric comparison'LIKE','NOT LIKE'— Pattern matching'IN','NOT IN'— Value in array'BETWEEN','NOT BETWEEN'— Range'EXISTS','NOT EXISTS'— Key exists'REGEXP','NOT REGEXP','RLIKE'— Regular expression
Type Values:
'NUMERIC','DECIMAL','SIGNED','UNSIGNED''CHAR','BINARY''DATE','DATETIME','TIME'
Search Parameters
| Variable | Type | Description |
|---|---|---|
s | string | Search keyword(s) |
search_columns | string[] | Columns to search |
sentence | bool | Search as exact phrase |
exact | bool | Exact match (no wildcards) |
// Basic search
's' => 'hello world'
// Exclude terms (prefix with -)
's' => 'pillow -sofa'
// Search specific columns
's' => 'hello',
'search_columns' => array( 'post_title', 'post_excerpt' )
// Exact phrase
's' => 'hello world',
'sentence' => trueSearch Columns:
'post_title''post_excerpt''post_content'
Ordering Parameters
| Variable | Type | Description |
|---|---|---|
orderby | `string | array` |
order | string | 'ASC' or 'DESC' |
orderby Values:
| Value | Description |
|---|---|
'none' | No order |
'ID' | Post ID |
'author' | Author ID |
'title' | Post title |
'name' | Post slug |
'type' | Post type |
'date' | Post date (default) |
'modified' | Last modified date |
'parent' | Parent post ID |
'rand' | Random |
'RAND(x)' | Random with seed |
'comment_count' | Number of comments |
'relevance' | Search relevance |
'menu_order' | Menu order |
'meta_value' | Meta value (requires meta_key) |
'meta_value_num' | Numeric meta value |
'post__in' | Preserve post__in order |
'post_name__in' | Preserve post_name__in order |
'post_parent__in' | Preserve post_parent__in order |
// Single orderby
'orderby' => 'title',
'order' => 'ASC'
// Multiple orderby
'orderby' => array(
'menu_order' => 'ASC',
'title' => 'ASC',
)
// Order by meta
'meta_key' => 'price',
'orderby' => 'meta_value_num',
'order' => 'ASC'
// Preserve post__in order
'post__in' => array( 5, 2, 8 ),
'orderby' => 'post__in'
// Random with seed (for consistent pagination)
'orderby' => 'RAND(123)'Parent/Hierarchy Parameters
| Variable | Type | Description |
|---|---|---|
post_parent | int | Parent post ID. 0 for top-level. |
post_parent__in | int[] | Parent IDs to include |
post_parent__not_in | int[] | Parent IDs to exclude |
// Children of post 10
'post_parent' => 10
// Top-level pages only
'post_type' => 'page',
'post_parent' => 0
// Children of multiple parents
'post_parent__in' => array( 10, 20 )Password Parameters
| Variable | Type | Description |
|---|---|---|
has_password | bool | true for protected, false for not |
post_password | string | Posts with specific password |
// Only password-protected posts
'has_password' => true
// Only non-protected posts
'has_password' => false
// Specific password
'post_password' => 'mypassword'Comment Parameters
| Variable | Type | Description |
|---|---|---|
comment_status | string | 'open' or 'closed' |
ping_status | string | 'open' or 'closed' |
comment_count | `int | array` |
comments_per_page | int | Comments per page |
// Posts with comments open
'comment_status' => 'open'
// Posts with exact comment count
'comment_count' => 10
// Posts with more than 5 comments
'comment_count' => array(
'value' => 5,
'compare' => '>'
)Permission Parameters
| Variable | Type | Description |
|---|---|---|
perm | string | Permission check: 'readable' or 'editable' |
// Only posts current user can read
'perm' => 'readable'MIME Type (Attachments)
| Variable | Type | Description |
|---|---|---|
post_mime_type | `string | string[]` |
// Only images
'post_type' => 'attachment',
'post_status' => 'inherit',
'post_mime_type' => 'image'
// Specific types
'post_mime_type' => array( 'image/jpeg', 'image/png' )Cache Control
| Variable | Type | Default | Description |
|---|---|---|---|
cache_results | bool | true | Cache post information |
update_post_meta_cache | bool | true | Prime meta cache |
update_post_term_cache | bool | true | Prime term cache |
update_menu_item_cache | bool | false | Prime menu item cache |
lazy_load_term_meta | bool | (varies) | Lazy-load term meta |
// Optimized query (no extra queries)
'cache_results' => true,
'update_post_meta_cache' => false, // Don't need meta
'update_post_term_cache' => false, // Don't need termsMiscellaneous
| Variable | Type | Description |
|---|---|---|
fields | string | Return format: '', 'ids', or 'id=>parent' |
no_found_rows | bool | Skip counting total rows |
suppress_filters | bool | Bypass filters |
ignore_sticky_posts | bool | Ignore sticky post handling |
menu_order | int | Specific menu order value |
// Return only IDs (fast)
'fields' => 'ids'
// Return ID => parent mapping
'fields' => 'id=>parent'
// Skip SQL_CALC_FOUND_ROWS (faster when not paginating)
'no_found_rows' => true
// Bypass all filters
'suppress_filters' => true
// Don't put stickies first
'ignore_sticky_posts' => trueMethods
Constructor
public function __construct( string|array $query = '' )Creates new query. If $query provided, immediately runs query().
Core Methods
query()
public function query( string|array $query ): WP_Post[]|int[]Sets up the query and retrieves posts.
Parameters:
$query— Query string or array
Returns: Array of posts or post IDs.
get_posts()
public function get_posts(): WP_Post[]|int[]Retrieves posts based on current query variables. Called internally by query().
parse_query()
public function parse_query( string|array $query = '' ): voidParses query string and sets query type flags.
Loop Methods
have_posts()
public function have_posts(): boolCheck if more posts available. Fires loop_end and loop_no_results actions.
the_post()
public function the_post(): voidAdvances to next post, sets up globals. Fires loop_start on first call.
rewind_posts()
public function rewind_posts(): voidResets loop to beginning.
next_post()
public function next_post(): WP_PostReturns next post in loop (internal use).
Comment Loop Methods
have_comments()
public function have_comments(): boolCheck if more comments available.
the_comment()
public function the_comment(): voidAdvances to next comment.
rewind_comments()
public function rewind_comments(): voidResets comment loop.
Getters/Setters
get()
public function get( string $query_var, mixed $default_value = '' ): mixedRetrieves query variable value.
set()
public function set( string $query_var, mixed $value ): voidSets query variable value.
get_queried_object()
public function get_queried_object(): WP_Term|WP_Post_Type|WP_Post|WP_User|nullReturns the main queried object based on query type.
get_queried_object_id()
public function get_queried_object_id(): intReturns ID of queried object, or 0.
Post Data Methods
setup_postdata()
public function setup_postdata( WP_Post|object|int $post ): trueSets up global post data. Fires the_post action.
generate_postdata()
public function generate_postdata( WP_Post|object|int $post ): array|falseGenerates postdata array without setting globals.
reset_postdata()
public function reset_postdata(): voidRestores $post global to current query’s post.
Conditional Methods
All return bool. Some accept optional parameters for specific checks.
| Method | Parameters |
|---|---|
is_archive() | — |
is_post_type_archive() | $post_types = '' |
is_attachment() | $attachment = '' |
is_author() | $author = '' |
is_category() | $category = '' |
is_tag() | $tag = '' |
is_tax() | $taxonomy = '', $term = '' |
is_date() | — |
is_day() | — |
is_month() | — |
is_year() | — |
is_time() | — |
is_feed() | $feeds = '' |
is_comment_feed() | — |
is_front_page() | — |
is_home() | — |
is_privacy_policy() | — |
is_page() | $page = '' |
is_paged() | — |
is_preview() | — |
is_robots() | — |
is_favicon() | — |
is_search() | — |
is_single() | $post = '' |
is_singular() | $post_types = '' |
is_trackback() | — |
is_404() | — |
is_embed() | — |
is_main_query() | — |
Internal Methods
init()
public function init(): voidResets all properties to defaults.
fill_query_vars()
public function fill_query_vars( array $query_vars ): arrayFills in missing query variables with defaults.
parse_tax_query()
public function parse_tax_query( array &$query_vars ): voidParses taxonomy-related query vars.
set_404()
public function set_404(): voidSets 404 state. Fires set_404 action.
Example Queries
Recent Posts with Thumbnails
$query = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 5,
'meta_query' => array(
array(
'key' => '_thumbnail_id',
'compare' => 'EXISTS',
),
),
) );Products by Price Range
$query = new WP_Query( array(
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_price',
'value' => array( 10, 50 ),
'type' => 'NUMERIC',
'compare' => 'BETWEEN',
),
),
'orderby' => 'meta_value_num',
'meta_key' => '_price',
'order' => 'ASC',
) );Posts in Multiple Taxonomies
$query = new WP_Query( array(
'post_type' => 'post',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => 'news',
),
array(
'taxonomy' => 'post_tag',
'field' => 'slug',
'terms' => array( 'featured', 'breaking' ),
'operator' => 'IN',
),
),
) );Complex Date Query
$query = new WP_Query( array(
'post_type' => 'event',
'date_query' => array(
array(
'after' => array(
'year' => 2023,
'month' => 6,
),
'before' => array(
'year' => 2023,
'month' => 12,
'day' => 31,
),
'inclusive' => true,
),
array(
'hour' => 9,
'compare' => '>=',
),
array(
'hour' => 17,
'compare' => '<=',
),
'relation' => 'AND',
),
) );Optimized ID-Only Query
$post_ids = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 100,
'fields' => 'ids',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
) );
// $post_ids->posts is array of integers