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

php
$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

PropertyTypeDescription
$queryarrayOriginal query vars as passed
$query_varsarrayParsed and filled query vars
$requeststringSQL query string

Results

PropertyTypeDescription
$posts`WP_Post[]int[]`
$post`WP_Postnull`
$post_countintNumber of posts in current page
$found_postsintTotal matching posts (all pages)
$max_num_pagesintNumber of pages
$current_postintIndex of current post (-1 before loop)

Queried Object

PropertyTypeDescription
$queried_object`WP_TermWP_Post_Type
$queried_object_idintID of queried object

Loop State

PropertyTypeDescription
$in_the_loopboolWhether currently in the loop
$before_loopboolWhether before the loop has started (since 6.3.0)

Query Type Flags

PropertyDescription
$is_singleSingle post (not page or attachment)
$is_pageSingle page
$is_attachmentSingle attachment
$is_singularAny single post/page/attachment
$is_previewPost preview
$is_archiveAny archive page
$is_categoryCategory archive
$is_tagTag archive
$is_taxCustom taxonomy archive
$is_authorAuthor archive
$is_dateAny date archive
$is_yearYear archive
$is_monthMonth archive
$is_dayDay archive
$is_timeTime archive
$is_post_type_archivePost type archive
$is_homeBlog home (posts page)
$is_front_page()Site front page (method, not property)
$is_privacy_policyPrivacy policy page
$is_searchSearch results
$is_feedFeed request
$is_comment_feedComments feed
$is_trackbackTrackback endpoint
$is_pagedPaginated (page 2+)
$is_adminAdmin request
$is_404No results found
$is_embedEmbedded post
$is_robotsrobots.txt request
$is_faviconfavicon.ico request
$is_posts_pagePage assigned as posts page

Sub-Query Objects

PropertyTypeDescription
$tax_query`WP_Tax_Querynull`
$meta_query`WP_Meta_Queryfalse`
$date_query`WP_Date_Queryfalse`

Comments

PropertyTypeDescription
$commentsWP_Comment[]Comments for current post
$commentWP_CommentCurrent comment in loop
$comment_countintNumber of comments
$current_commentintCurrent comment index
$max_num_comment_pagesintNumber of comment pages

Query Variables Reference

Post Selection

By ID

VariableTypeDescription
pintPost ID
post__inint[]Array of post IDs to include
post__not_inint[]Array of post IDs to exclude
page_idintPage ID
php
// 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

VariableTypeDescription
namestringPost slug
pagenamestringPage slug (supports hierarchy: parent/child)
post_name__instring[]Array of post slugs
titlestringExact post title match
php
// By slug
'name' => 'hello-world'

// By page path
'pagename' => 'about/team'

// Multiple slugs
'post_name__in' => array( 'hello', 'world' )

Post Type & Status

VariableTypeDescription
post_type`stringstring[]`
post_status`stringstring[]`

Post Type Values:

  • 'post' — Blog posts
  • 'page' — Pages
  • 'attachment' — Media
  • 'revision' — Revisions
  • 'nav_menu_item' — Menu items
  • 'any' — All types except revisions and types with exclude_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 except trash and auto-draft
php
// Multiple post types
'post_type' => array( 'post', 'page', 'product' )

// Multiple statuses
'post_status' => array( 'publish', 'private' )

Pagination

VariableTypeDescription
posts_per_pageintPosts per page. -1 for all.
posts_per_archive_pageintPosts per page on archives
nopagingboolDisable pagination
pagedintPage number
offsetintNumber of posts to skip
pageintPage number for static front page
php
// 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' => true

Category Parameters

VariableTypeDescription
cat`intstring`
category_namestringCategory slug (includes children)
category__inint[]Category IDs (no children)
category__not_inint[]Exclude category IDs
category__andint[]Posts in ALL listed categories
php
// 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

VariableTypeDescription
tagstringTag slug(s). Comma = OR, plus = AND
tag_idintTag ID
tag__inint[]Tag IDs (OR)
tag__not_inint[]Exclude tag IDs
tag__andint[]Posts with ALL tags
tag_slug__instring[]Tag slugs (OR)
tag_slug__andstring[]Tag slugs (AND)
php
// 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)

VariableTypeDescription
tax_queryarrayComplex taxonomy query

tax_query Structure:

php
'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

VariableTypeDescription
author`intstring`
author_namestringAuthor nicename (slug)
author__inint[]Author IDs to include
author__not_inint[]Author IDs to exclude
php
// 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

VariableTypeDescription
yearintFour-digit year
monthnumintMonth (1-12)
dayintDay of month (1-31)
wintWeek of year (0-53)
hourintHour (0-23)
minuteintMinute (0-59)
secondintSecond (0-59)
mintYearMonth (e.g., 202301)
date_queryarrayComplex date query
php
// 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

VariableTypeDescription
meta_keystringCustom field key
meta_valuestringCustom field value
meta_comparestringComparison operator
meta_typestringData type for CAST
meta_queryarrayComplex meta query

Simple Meta Query:

php
// 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:

php
'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 clause

Compare 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

VariableTypeDescription
sstringSearch keyword(s)
search_columnsstring[]Columns to search
sentenceboolSearch as exact phrase
exactboolExact match (no wildcards)
php
// 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' => true

Search Columns:

  • 'post_title'
  • 'post_excerpt'
  • 'post_content'

Ordering Parameters

VariableTypeDescription
orderby`stringarray`
orderstring'ASC' or 'DESC'

orderby Values:

ValueDescription
'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
php
// 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

VariableTypeDescription
post_parentintParent post ID. 0 for top-level.
post_parent__inint[]Parent IDs to include
post_parent__not_inint[]Parent IDs to exclude
php
// 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

VariableTypeDescription
has_passwordbooltrue for protected, false for not
post_passwordstringPosts with specific password
php
// Only password-protected posts
'has_password' => true

// Only non-protected posts
'has_password' => false

// Specific password
'post_password' => 'mypassword'

Comment Parameters

VariableTypeDescription
comment_statusstring'open' or 'closed'
ping_statusstring'open' or 'closed'
comment_count`intarray`
comments_per_pageintComments per page
php
// 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

VariableTypeDescription
permstringPermission check: 'readable' or 'editable'
php
// Only posts current user can read
'perm' => 'readable'

MIME Type (Attachments)

VariableTypeDescription
post_mime_type`stringstring[]`
php
// Only images
'post_type'      => 'attachment',
'post_status'    => 'inherit',
'post_mime_type' => 'image'

// Specific types
'post_mime_type' => array( 'image/jpeg', 'image/png' )

Cache Control

VariableTypeDefaultDescription
cache_resultsbooltrueCache post information
update_post_meta_cachebooltruePrime meta cache
update_post_term_cachebooltruePrime term cache
update_menu_item_cacheboolfalsePrime menu item cache
lazy_load_term_metabool(varies)Lazy-load term meta
php
// 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 terms

Miscellaneous

VariableTypeDescription
fieldsstringReturn format: '', 'ids', or 'id=>parent'
no_found_rowsboolSkip counting total rows
suppress_filtersboolBypass filters
ignore_sticky_postsboolIgnore sticky post handling
menu_orderintSpecific menu order value
php
// 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' => true

Methods

Constructor

php
public function __construct( string|array $query = '' )

Creates new query. If $query provided, immediately runs query().


Core Methods

query()

php
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()

php
public function get_posts(): WP_Post[]|int[]

Retrieves posts based on current query variables. Called internally by query().


parse_query()

php
public function parse_query( string|array $query = '' ): void

Parses query string and sets query type flags.


Loop Methods

have_posts()

php
public function have_posts(): bool

Check if more posts available. Fires loop_end and loop_no_results actions.


the_post()

php
public function the_post(): void

Advances to next post, sets up globals. Fires loop_start on first call.


rewind_posts()

php
public function rewind_posts(): void

Resets loop to beginning.


next_post()

php
public function next_post(): WP_Post

Returns next post in loop (internal use).


Comment Loop Methods

have_comments()

php
public function have_comments(): bool

Check if more comments available.


the_comment()

php
public function the_comment(): void

Advances to next comment.


rewind_comments()

php
public function rewind_comments(): void

Resets comment loop.


Getters/Setters

get()

php
public function get( string $query_var, mixed $default_value = '' ): mixed

Retrieves query variable value.


set()

php
public function set( string $query_var, mixed $value ): void

Sets query variable value.


get_queried_object()

php
public function get_queried_object(): WP_Term|WP_Post_Type|WP_Post|WP_User|null

Returns the main queried object based on query type.


get_queried_object_id()

php
public function get_queried_object_id(): int

Returns ID of queried object, or 0.


Post Data Methods

setup_postdata()

php
public function setup_postdata( WP_Post|object|int $post ): true

Sets up global post data. Fires the_post action.


generate_postdata()

php
public function generate_postdata( WP_Post|object|int $post ): array|false

Generates postdata array without setting globals.


reset_postdata()

php
public function reset_postdata(): void

Restores $post global to current query’s post.


Conditional Methods

All return bool. Some accept optional parameters for specific checks.

MethodParameters
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()

php
public function init(): void

Resets all properties to defaults.


fill_query_vars()

php
public function fill_query_vars( array $query_vars ): array

Fills in missing query variables with defaults.


parse_tax_query()

php
public function parse_tax_query( array &$query_vars ): void

Parses taxonomy-related query vars.


set_404()

php
public function set_404(): void

Sets 404 state. Fires set_404 action.


Example Queries

Recent Posts with Thumbnails

php
$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

php
$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

php
$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

php
$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

php
$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