wppaste
WordPress

get_posts( array $args = null ): WP_Post[]|int[]

Since
1.2.0
Source
wp-includes/post.php:2543

Retrieve an array of posts matching your criteria with get_posts(), a WP_Query wrapper that returns post objects without pagination overhead. It defaults to the 5 latest posts and accepts every WP_Query argument plus aliases like numberposts, category, include, and exclude. Sticky handling and found-rows counting are always disabled, so use WP_Query directly when you need pagination.

Retrieves an array of the latest posts, or posts matching the given criteria.

Description

For more information on the accepted arguments, see the https://developer.wordpress.org/reference/classes/wp_query/ WP_Query documentation in the Developer Handbook.

The $ignore_sticky_posts and $no_found_rows arguments are ignored by this function and both are set to true.

The defaults are as follows:

Compatibility

WordPress
since 1.2.0
PHP
7.4–8.6-dev
  • 6.7.7
  • 6.8.8
  • 6.9.7
  • 7.0.4
  • 7.1.0

Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.

Parameters

$argsarrayoptional
Arguments to retrieve posts. See WP_Query::parse_query() for all available arguments.Default: null
  • $numberpostsintdefault: 5

    Total number of posts to retrieve. Is an alias of $posts_per_page in WP_Query. Accepts -1 for all.
  • $categoryint|stringdefault: 0

    Category ID or comma-separated list of IDs (this or any children). Is an alias of $cat in WP_Query.
  • $includeint[]default: empty array

    An array of post IDs to retrieve, sticky posts will be included. Is an alias of $post__in in WP_Query.
  • $excludeint[]default: empty array

    An array of post IDs not to retrieve.
  • $suppress_filtersbooldefault: true

    Whether to suppress filters.

Return value

WP_Post[]|int[]
Array of post objects or post IDs.

Code examples

Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.

List the five latest posts

Switch the sandbox below to see the same call against a custom post type.

$latest = get_posts( array(
	'numberposts' => 5,
	'post_type'   => post_type_exists( 'book' ) ? 'book' : 'post',
) );

if ( ! $latest ) {
	echo 'Nothing matched.';
}

foreach ( $latest as $item ) {
	echo '- ', get_the_title( $item ), ' (', $item->post_type, ")\n";
}

post_type_exists() is only here so the one snippet works in both sandboxes.

Order results by a numeric custom field

Combining meta_key with orderby meta_value_num sorts by the field and, as a side effect, excludes posts that do not have it.

$priced = get_posts( array(
	'post_type'   => 'post',
	'meta_key'    => 'price',
	'orderby'     => 'meta_value_num',
	'order'       => 'ASC',
	'numberposts' => 5,
) );

if ( ! $priced ) {
	echo 'No posts carry a price.';
}

foreach ( $priced as $item ) {
	echo get_the_title( $item ), ' costs ', get_post_meta( $item->ID, 'price', true ), "\n";
}

Use meta_value_num rather than meta_value, or 100 sorts before 9.

Performance profile

How much work a call to get_posts() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.

Cost class
Heavy

Reaches the database via ->query().

Scaling
Constant

No loop in the body: the same number of instructions runs whatever you pass in.

Instructions
28–53

Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 63.

Plugin surface
None

Nothing here hands control to plugin code.

Called by
27

27 places in core call this, so the cost is paid more often than your own code shows.

What it touches

  • querycontent queryget_posts()this function does it
  • sqldatabase query->query()called directly

Further down the call graph this can also reach hook. That is the worst case, several calls deep and usually down an error path, not what a normal call pays.

What one call costs · 2 distinct outcomes

One number would be a lie: the work depends on which branch runs. These are every distinct cost get_posts() can have, taken from its control-flow graph on PHP 8.5.

WhenInstructionsCalls it makes
empty($parsed_args)28–43wp_parse_args(), ->query()
!empty($parsed_args)35–53wp_parse_args(), wp_parse_id_list(), ->query()

Across PHP versions

Compiles the same on PHP 7.4, 8.1, 8.2, 8.3, 8.4, 8.5 and 8.6-dev: 63 instructions, 28–53 executed per call, 7 branches. The work does not change between versions.

An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.

Uses · 3

Used by · 27

Show all 27

Source code

function get_posts( $args = null ) {	$defaults = array(		'numberposts'      => 5,		'category'         => 0,		'orderby'          => 'date',		'order'            => 'DESC',		'include'          => array(),		'exclude'          => array(),		'meta_key'         => '',		'meta_value'       => '',		'post_type'        => 'post',		'suppress_filters' => true,	); 	$parsed_args = wp_parse_args( $args, $defaults );	if ( empty( $parsed_args['post_status'] ) ) {		$parsed_args['post_status'] = ( 'attachment' === $parsed_args['post_type'] ) ? 'inherit' : 'publish';	}	if ( ! empty( $parsed_args['numberposts'] ) && empty( $parsed_args['posts_per_page'] ) ) {		$parsed_args['posts_per_page'] = $parsed_args['numberposts'];	}	if ( ! empty( $parsed_args['category'] ) ) {		$parsed_args['cat'] = $parsed_args['category'];	}	if ( ! empty( $parsed_args['include'] ) ) {		$incposts                      = wp_parse_id_list( $parsed_args['include'] );		$parsed_args['posts_per_page'] = count( $incposts );  // Only the number of posts included.		$parsed_args['post__in']       = $incposts;	} elseif ( ! empty( $parsed_args['exclude'] ) ) {		$parsed_args['post__not_in'] = wp_parse_id_list( $parsed_args['exclude'] );	} 	$parsed_args['ignore_sticky_posts'] = true;	$parsed_args['no_found_rows']       = true; 	$get_posts = new WP_Query();	return $get_posts->query( $parsed_args );}

Changelog

Introduced in 1.2.0. One change between 6.7.7 and 7.1.0.

  1. 6.7.7
  2. 6.8.8
  3. 6.9.7
  4. 7.0.4
  5. 7.1.0

Signature, return type and hooks compared across 5 parsed releases.

7.0.4
Parameter $args retyped from array to array|string.verified against source
1.2.0
Introduced.from the docblock

About this page

Parsed data
Generated from the wordpress-develop 6.8.8 tag, from src/wp-includes/post.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.
Corrections
Something wrong on this page? Report it and it gets fixed in the next regeneration.