WordPress Query Posts by Category, Tag, Custom attribute, and more!

Learn how to List Posts in WordPress using Category name, Tag name, Custom attributes, Post type, Publish date, Random posts, etc. For post listing in WordPress, we use get_posts function to retrieve any WordPress post with desired attributes.

3 from 5
from 2 user
(Rate this post)

Listing posts is one of the primary parts of developing WordPress. In this tutorial, I will show you the correct way of listing posts in WordPress (Programmatically).

Retrieve posts in WordPress using get_posts function

get_posts function is responsible for getting WordPress posts in an array.

This function accepts an argument (array) which we use to describe what posts exactly do we want to get in the returning array.

Let’s look at this function syntax.

get_posts function syntax in WordPress

Simple get_posts syntax:

get_posts($args)

$args parameters is an Array and it can be Null. It means that it’s optional to specify arguments for get_posts function.

Now check out the list of available arguments for this function.

Available arguments for get_posts function in WordPress

get_posts function arguments:

  • numberposts
  • category
  • post_type
  • post_status
  • meta_query
  • meta_key
  • meta_value
  • post_parent
  • s
  • tax_query
  • date_query
  • paged
  • orderby
  • sort_order
  • posts_per_page
  • offset
  • include
  • exclude
  • suppress_filters

numberposts argument in get_posts function

This argument specifies the number of posts you want to retrieve.

It accepts an integer value.

You can pass -1 value to receive all posts in an array.

Default value for numberposts argument is 5.

category argument

Value can be from the type of Integer or String.

When you pass an integer for the category, it refers to the category ID.

You can pass series of comma-separated IDs.

Default value for category argument is 0.

post_type argument

WordPress has different post types, they are regular posts and pages. WordPress also lets developers add their own post types.

If you installed the Woocommerce plugin, another post type named product will be added to the list.

post_type argument specifies the type of the post. the default value for this argument posts, not pages. this means if you do not specify post_type, posts will be retrieved not other post types like pages, products, or other custom post types (if available).

post_status argument

The status of posts you want to retrieve.

WordPress developers can add their own statuses as well.

Value of post_status can be one of these (or a custom post type added by a plugin):

  • publish
  • future
  • pending
  • draft
  • auto-draft
  • private
  • trash
  • inherit

meta_query argument

This argument helps you retrieve posts using custom fields relations.

meta_query value is an array of arrays.

meta_key argument

This argument also helps you to retrieve posts using custom fields.

meta_key + meta_value and meta_compare can give you posts with a specific custom field.

meta_key is the name of the custom field you want to retrieve, but you must provide a value for the meta_value parameter as well.

meta_value argument

This argument specifies the value of meta_key you want to retrieve.

meta_compare argument

This argument specifies the relation between meta_key and meta_value you’ve provided.

If you do not specify this argument’s value, the default comparison relation will be equality (=).

post_parent argument

This argument specifies the parent ID of a post (page or whatever).

This parameter receives an integer. but the default value is NULL.

s argument

If you want to search inside posts, like finding a word in the titles or contents, you can use the s argument.

tax_query argument

This argument will help developers retrieving posts in specific taxonomy (category or custom taxonomy).

Value is from type array and the syntax is like below. You need to specify taxonomy, field, and terms.

tax_query value for categories:

array(
	"taxonomy" => "category",
	"field"    => "slug",
	"terms"    => "category-slug-here, another-slug"
)

date_query argument

This argument will help you query posts based on dates.

The value type of this argument is an array with specific keys:

  • year
  • month
  • week
  • day
  • hour
  • minute
  • second
  • after
  • before
  • inclusive
  • compare
  • column (default: post_date)
  • relation (OR or AND).

paged argument

Pagination ability in sets of posts is available using paged argument.

paged is specifying which page of the posts list must be retrieved.

orderby argument

This argument will specify the order of the posts you want to retrieve, and it can be one of these values:

  • ID
  • author
  • title
  • name
  • type
  • date
  • modified
  • parent
  • rand
  • comment_count

sort_order argument

The sort order can be ASC for ascending or DESC for descending order.

posts_per_page argument

This argument is an alias for numberposts but with a little difference.

posts_per_page is specifying the number of posts per page, but numberposts is specifying the whole post set number (which does not matter for you anyway! usually you want posts on the page we are in)

You can practically use posts_per_page or numberposts to specify the number of posts you want to retrieve.

The default value for posts_per_page argument is defined on your WordPress settings page.

offset argument

This argument specifies how many posts you want to ignore before you start with your post list.

For example, if you have 20 posts, when you set offset to 5, you will ignore the first 5 post items and get the posts from 6 to whatever you specified.

include argument

For those who want to include specific post ids or slugs to the query, WordPress added include argument to the list.

This argument tells the get_posts function to retrieve posts only from these IDs or slugs.

exclude argument

If developers want to exclude specific post IDs or slugs from retrieving, they can use exclude argument.

This argument’s value can be an ID or slug of a post (comma-separated IDs or slugs).

suppress_filters argument

This argument helps developers to prevent filters from altering the query. The default value for suppress_filters is true.

What is the data structure returned from get_posts function in WordPress?

When you run the get_posts function, if it finds any post matching required arguments, it will return an array of post objects.

The post object will have the ID, Author, Date, Title, Excerpt, Status, Comment Status, Ping Status, Password, Slug, Comment Count, Type, ETC.

The full structure of a post object
WP_Post Object
(
    [ID]
    [post_author]
    [post_date] 
    [post_date_gmt] 
    [post_content] 
    [post_title] 
    [post_excerpt] 
    [post_status]
    [comment_status]
    [ping_status] 
    [post_password]
    [post_name]
    [to_ping]
    [pinged] 
    [post_modified]
    [post_modified_gmt]
    [post_content_filtered] 
    [post_parent] 
    [guid] 
    [menu_order]
    [post_type]
    [post_mime_type] 
    [comment_count]
    [filter]
)

Query WordPress posts using get_posts function examples

I will continue this tutorial with a few promised examples of using get_posts. you can use these codes in your theme or your WordPress plugin development.

Query posts by Category ID

category argument can help you retrieve posts with category ID.

As I told you before, You can pass series of comma-separated IDs for multiple categories.

//set category id to 1
$categoryId = 1;

//set arguments for the category
$args = array(
	"category"=>$categoryId,
);

//query posts
$posts = get_posts($args);

//print post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Query Posts by Category Slug

The best way to get posts by category slug in WordPress is to first get the ID of the category, then use category argument for that ID.

We use get_category_by_slug function in WordPress to get the category object.

Working Example for a category named “uncategorized”:

$categorySlug = "uncategorized";

//get the category from wordpress
$category = get_category_by_slug($categorySlug);

//check if the category exists
if($category){

	//set category id to term_id (category is a term)
	$categoryId = $category->term_id;

	//set the arguments for the categoryId
	$args = array(
		"category"=>$categoryId,
	);

	//query posts
	$posts = get_posts($args);

	//printing post titles
	foreach ($posts as $post){
		echo "Title: ".$post->post_title." <br />";
	}
}

Query Posts by Tag Slug

tax_query argument will help us retrieve posts using tag slug.

taxonomy key of tax_query array item must be set to post_tag, the field must be set to slug and terms is what we looking for (value, the tag slug).

//set tag slug
$tagSlug = "test";

//set the arguments for the tag
$args = array(
	'tax_query'      => array(
		array(
			'taxonomy'  => 'post_tag',
			'field'     => 'slug',
			'terms'     => sanitize_title( $tagSlug )
		)
	)
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Query Posts by Custom Attribute

We have two options to do this:

The first one is to use meta_key and meta_value arguments of get_posts.

This code retrieves all posts with a custom field named “featured” set to “yes”:

//set the arguments for the custom field named "featured" with value "yes"
$args = array(
	'meta_key' => 'featured',
	'meta_value' => 'yes',
	'meta_compare' => '=',//optional!
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

The second one is to use meta_query argument which can help us use multiple custom attributes.

For example, the below code will retrieve posts with two custom attributes (featured & top) set to yes value:

//for featured and top custom fields set to yes
$args = array(
	'meta_query' => array(
		array(
			'key' => 'featured',
			'value'   => 'yes',
			'compare' => '='//optional!
		),
		array(
			'key' => 'top',
			'value'   => 'yes',
			'compare' => '='//optional!
		),
	)
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Query posts by Publish Date

WordPress publish date for posts can be set automatically or manually through the WordPress admin panel when you are editing the post. (You can also set publish date for WordPress posts programmatically)

WordPress lets developers use query_dates argument to retrieve posts with a date specification.

We will retrieve posts older or newer than a specified date:

Post older than the Date

The working code for retrieving posts before “30-07-2021”:

//set arguments for dates before 30-07-2021
$args = array(
	'date_query' => array(
		array(
			'before' => '30-07-2021'
        )
    )
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Posts newer than the Date

The working code for retrieving posts after “30-07-2021”:

//set arguments for dates before 30-07-2021
$args = array(
	'date_query' => array(
		array(
			'after' => '30-07-2021'
        )
    )
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Query posts by Post Type

post_type argument can help us retrieve posts of a specific type, like pages:

//set the post type
$postType = "page";

//set arguments for post type
$args = array(
	'post_type' => $postType
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Query posts with a word inside

We use s agument to search for a world inside posts.

The working code to search “test” word inside posts is this:

//set the word to search
$search = "test";

//set arguments for search
$args = array(
	's' => $search
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Query random posts

We have to set the orderby argument to rand, if we want to retrieve posts in random order:

//set order for random posts
$args = array(
	'orderby' => 'rand'
);

//query posts
$posts = get_posts($args);

//printing post titles
foreach ($posts as $post){
	echo "Title: ".$post->post_title." <br />";
}

Where can I find more information about query posts in WordPress?

The first place to find information about anything is the WordPress official website. Specific pages you may want to explore are the get_posts function page, and the WP_Post class page.

If you faced any problem using WordPress functions, you can ask your questions on WordPress StackExchange.

If you want to continue learning WordPress, I recommend you read my tutorial:

WordPress Action and Filter Hooks Tutorial (+10 Examples)

What do you think about "WordPress Query Posts by Category, Tag, Custom attribute, and more!"?

Your rating submit was successfull.

Your rating submit was not successfull.

Menu