1

I have looked in the WP codex for an example which shows how to use a taxonomy query to retrieve a set of posts that have no post_format.

IOW: 'All posts where an aside or quote or link...etc... post_format has not been assigned; eg. a 'standard' post_format.'

But I can't seem to figure out how to query for posts that have -no- post_format.

IOW: it seems as though if the post has no post_format (eg. 'aside' or 'quote') it returns an empty result in get_post_format()

$args = array(
  'post_type' => 'post',
  'tax_query' => array(
    array(
      'taxonomy' => 'post_format',
      'field' => 'slug',
      'terms' => array(?????)
     )
   )
);
$query = new WP_Query( $args );

How does one set up this kind of query?

1 Answer 1

2

You have to query post that has no post format attached:

$args = array(
  'post_type' => 'post',
  'tax_query' => array(
    array(
      'taxonomy' => 'post_format',
      'field' => 'slug',
      'operator' => 'NOT IN',
      'terms' => get_terms('post_format')
    )
  )
);

To improve performance you can hardcoding the post format instead of using get_terms to retrieve them:

$args = array(
  'post_type' => 'post',
  'tax_query' => array(
    array(
      'taxonomy' => 'post_format',
      'field' => 'slug',
      'operator' => 'NOT IN',
      'terms' => array('post_format-aside','post_format-chat','post_format-gallery','post_format-link','post_format-image','post_format-quote','post_format-status','post_format-video','post_format-audio')
    )
  )
);

Edit

Once you ask for it in comments, I'll give you the raw SQL query that can perform same task. Please note that once post without post format are not stored anywhere (standard post format means no post format), to obtain what you want you need to nest 2 queries with the nested containing a join among 3 tables. This is very far from what you can call a performant query. For this it's a good idea cache the result in a transient:

function post_without_formats() {
    $cached = get_transient('post_without_formats');
    if ( $cached ) return $cached;
    global $wpdb;
    $post_without_format = $wpdb->get_results(
      "SELECT * FROM $wpdb->posts WHERE post_status = 'publish'
       AND post_type = 'post' AND ID NOT IN (
         SELECT p.ID FROM $wpdb->posts as p
         LEFT JOIN $wpdb->term_relationships as tr ON tr.object_id = p.ID
         LEFT JOIN $wpdb->term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
         WHERE p.post_status = 'publish' AND p.post_type = 'post'
         AND tt.taxonomy = 'post_format'
         GROUP BY p.ID
       )"
    );
    set_transient('post_without_formats', $post_without_format);
    return $post_without_format;
}

function reset_post_without_formats($term, $taxonomy) {
  if ( $taxonomy == 'post_format' ) {
    delete_transient('post_without_formats');
    post_without_formats();
  }
}

add_action('edited_term_taxonomy', 'reset_post_without_formats', 99, 2);

As you can see I reset the transient everytime a post format is added or removed from a post. This will slow down a bit your backend but will increase the frontend speed.

4
  • Thanks. I'll do some testing and report back. I prefer #1--even though it's slower, simply because those options will certainly be expanded over time. I still think there should be a faster solution that uses a direct SQL statement... just can't figure out what it is. Best.
    – jchwebdev
    Oct 8, 2013 at 17:54
  • @jchwebdev get_terms is more or less a wrapper for a SQL query.. an most important it use cache, direct SQL don't... so, SQL query will not be faster. After that I'm not so sure post format terms will be expanded, they are are just taxonomy terms, the only reason why there's a sense to their existence is to give a restricted number of taxonomy terms sharing same slug among all the thousand themes that exists for WP. If this number of terms become too large I think post format become useless.
    – gmazzap
    Oct 8, 2013 at 18:06
  • Thanks. I understand, but it seems to me that there must be a relation to the taxonomy table to get the terms, so it should be possible to do something like a JOIN which shows all posts which return NULL for that join. I just don't know what it is.
    – jchwebdev
    Oct 8, 2013 at 21:21
  • Cool. Thanks for all the hard work. I'll report back as soon as I have a moment to play with it. Best. ---JC
    – jchwebdev
    Oct 9, 2013 at 3:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.