wp-includes/post.php:2582Retrieve 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.
$argsarray|stringoptionalnull$numberpostsintdefault: 5
$categoryint|stringdefault: 0
$includeint[]default: empty array
$excludeint[]default: empty array
$suppress_filtersbooldefault: true
WP_Post[]|int[]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.
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.
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.
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 );}Introduced in 1.2.0. One change between 6.7.7 and 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
$args retyped from array to array|string.verified against sourcesrc/wp-includes/post.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.