Post Format Queries

Posted on

By Michael Fields

I recently finished a custom plugin for a client and after I shipped it to him, he wrote back asking if I could make a small modification. Basically, there was a loop that displayed a certain number of posts and he wanted to excluded posts formatted as “links”. It dawned on me that I have never really done this before and was excited make it happen!

I knew that this should be relatively easy to accomplish. WordPress 3.1 extended the way that taxonomies can be queried which allows for a great deal of fine tuning. Read more about Advanced Taxonomy Queries in WordPress.

So, without further ado, here’s the solution … as well as a couple of things I learned along the way.

5 Most Recent Posts – No Links

Passing the tax_query argument to get_posts(). The following configuration allows you to exclude all posts having the “Link” post format.

$no_links = get_posts( array(
	'tax_query' => array(
		array(
		  'taxonomy' => 'post_format',
		  'field'    => 'slug',
		  'terms'    => array( 'post-format-link' ),
		  'operator' => 'NOT IN'
		)
	)
) );

Only Links

By replacing NOT IN with IN for the operator argument, we can easily make the query return only link posts.

$links = get_posts( array(
	'tax_query' => array(
		array(
		  'taxonomy' => 'post_format',
		  'field'    => 'slug',
		  'terms'    => array( 'post-format-link' ),
		  'operator' => 'IN'
		)
	)
) );

More Than Just Links!

If you need to include or exclude posts of another format, you can modify the value of the terms arg with anything from the following list:

  • post-format-aside
  • post-format-audio
  • post-format-chat
  • post-format-gallery
  • post-format-image
  • post-format-link
  • post-format-status
  • post-format-quote
  • post-format-video

Combine a Few Different Post Formats

The terms arg has been designed specifically to enable you to include or exclude more than one term. If you wanted to exclude both links and status updates from your query, the following should do the trick.

$exclude_links_and_status = get_posts( array(
	'tax_query' => array(
		array(
		  'taxonomy' => 'post_format',
		  'field'    => 'slug',
		  'terms'    => array( 'post-format-link', 'post-format-status' ),
		  'operator' => 'NOT IN',
		)
	)
) );

Showing Only Standard Posts

Perhaps you have a blog with posts of many, many different formats (These are good problems to have btw. I only use two ). What do you do if you only want to display a list of regular-old-posts? You’ll probably want to exclude all of the post formats.

Get a List of All Post Formats

$formats = get_post_format_slugs();

Massage the Post Formats

The get_post_format_slugs() function returns the simple, easy to read name for each post format. We will need to use the long-form name of the post format in our query. We’ll just loop over format names and add a bit of info to the beginning of name.

foreach ( (array) $formats as $i => $format ) {
	$formats[$i] = 'post-format-' . $format;
}

Run the Query

All that’s left to do is pass of the the formats as the terms argument and set the operator argument to NOT IN.

$standard_posts = get_posts( array(
	'tax_query' => array(
		array(
		  'taxonomy' => 'post_format',
		  'field'    => 'slug',
		  'terms'    => $formats,
		  'operator' => 'NOT IN'
		)
	)
) );

Here’s all of it together for easy copy-and-paste. I even threw in a simple loop at no extra charge!

$formats = get_post_format_slugs();

foreach ( (array) $formats as $i => $format ) {
	$formats[$i] = 'post-format-' . $format;
}

$standard_posts = get_posts( array(
	'tax_query' => array(
		array(
		  'taxonomy' => 'post_format',
		  'field'    => 'slug',
		  'terms'    => $formats,
		  'operator' => 'NOT IN'
		)
	)
) );

global $post;

foreach( (array) $standard_posts as $post ) {
	setup_postdata( $post );
	print '<div>';
	the_title( '<h2>', '</h2>' );
	the_content();
	print '</div>';
}

wp_reset_postdata();

6 Comments Comments are closed

  1. shawn July 12, 2011 at 9:00 pm

    Here’s to hoping that someday wp simply adds ‘standard’ to standard post-formats.

    Right now I have an easy url structure for all other forumat archive pages

    */type/images/

    However it seems that I can’t do this automatically with standard post formats… kind of annoying actually.

    b.t.w. great writeup

  2. Brian Krogsgard July 13, 2011 at 3:46 am

    This, sir, is a golden snippet.

    Thanks : )

  3. Michael Fields July 13, 2011 at 3:58 am

    Thanks Brian. Glad you like!
    But … wait a second, did you just say “Golden Snippet”? Sounds a lot like “Golden Ticket” to me. And don’t you write for that site about the candy? The WordPress candy? If memory serves there’s a big factory there where you make the WordPress candy. I’ve even seen pictures! If I were to put two and two together here, I might be let to the assumption that I have just won a free trip to the WPCandy Factory! Is it so? Can it really true?

  4. Brian Krogsgard July 13, 2011 at 4:01 am

    It is so true! Come on board!

  5. Michael Fields July 13, 2011 at 4:07 am

    Yay! I’m hoping for a chocolate river :)

  6. Michael Fields July 14, 2011 at 1:46 am

    Thanks Shawn! Glad you liked it. On the topic of “Standard Posts” I kinda agree and disagree all at the same time (imagine that). I definitely agree that not having an automatic rewrite for standard posts is a bit of an inconsistency. But adding a custom one shouldn’t be too hard. Personally, I would probably create a custom page template and pass a modified version of the last query above to query_posts(). It’s probably the easiest solution.

    I do, however, disagree that they should be automatically associated with a “standard” format. While I see how this does make sense (as “standard” is the label of the radio button shown in the edit post screen), it also doesn’t make sense from another perspective. I mean, when you format a post as a link or an aside you are adding something to it. In the event of a “standard” post, there is really no need to add something new to it. It’s just a post with no format. Not a post with the format of standard.

    Honestly, both of these things make sense to me :) Not sure which is “correct”.

Fork me on GitHub