How to query for posts without a post_format

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.’

Read More

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?

Related posts

1 comment

  1. 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.

Comments are closed.