Guest User

WP - Get posts that don't have a particular meta key

a guest
Nov 2nd, 2010
1,232
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2. /*
  3.     $meta_key    - What meta key to check against (required)
  4.     $post_type   - What post type to check (default - post)
  5.     $post_status - What post status to check (default - publish)
  6.     $fields      - Whether to query all the post table columns, or just a select one ... all, titles, ids, or guids (all returns an array of objects, others return an array of values)
  7. */
  8. function posts_without_meta( $meta_key = '', $post_type = 'post', $post_status = 'publish', $fields = 'all' ) {
  9.     global $wpdb;
  10.    
  11.     if( !isset( $meta_key ) || !isset( $post_type ) || !isset( $post_status ) || !isset( $fields ) )
  12.         return false;
  13.    
  14.     // Meta key is required
  15.     if( empty( $meta_key ) )
  16.         return false;
  17.    
  18.     // All parameters are expected to be strings
  19.     if( !is_string( $meta_key ) || !is_string( $post_type ) || !is_string( $post_status ) || !is_string( $fields ) )
  20.         return false;
  21.    
  22.     if( empty( $post_type ) )
  23.         $post_type = 'post';
  24.    
  25.     if( empty( $post_status ) )
  26.         $post_status = 'publish';
  27.  
  28.     if( empty( $fields ) )
  29.         $fields = 'all';
  30.    
  31.     // Since all parameters are strings, bind them into one for a cheaper preg match (rather then doing one for each)
  32.     $possibly_unsafe_text = $meta_key . $post_type . $post_status . $fields;
  33.    
  34.     // Simply die if anything not a letter, number, underscore or hyphen is present
  35.     if( preg_match( '/([^a-zA-Z0-9_-]+)/', $possibly_unsafe_text ) ) {
  36.         wp_die( 'Invalid characters present in call to function (valid chars are a-z, 0-9, A-Z, underscores and hyphens).' );
  37.         exit;
  38.     }
  39.    
  40.     switch( $fields ) :
  41.         case 'ids':
  42.             $cols = 'p.ID';
  43.             break;
  44.         case 'titles':
  45.             $cols = 'p.post_title';
  46.             break;
  47.         case 'guids':
  48.             $cols = 'p.guid';
  49.             break;
  50.         case 'all':
  51.         default:
  52.             $cols = 'p.*';
  53.             break;
  54.     endswitch;
  55.    
  56.     if( 'all' == $fields )
  57.         $result = $wpdb->get_results( $wpdb->prepare( "
  58.             SELECT $cols FROM {$wpdb->posts} p
  59.             WHERE NOT EXISTS
  60.             (
  61.                 SELECT pm.* FROM {$wpdb->postmeta} pm
  62.                 WHERE p.ID = pm.post_id
  63.                 AND pm.meta_key = '%s'
  64.             )
  65.             AND p.post_type = '%s'
  66.             AND p.post_status = '%s'
  67.             ",
  68.             $meta_key,
  69.             $post_type,
  70.             $post_status
  71.         ) );
  72.     // get_col is nicer for single column selection (less data to traverse)
  73.     else
  74.         $result = $wpdb->get_col( $wpdb->prepare( "
  75.             SELECT $cols FROM {$wpdb->posts} p
  76.             WHERE NOT EXISTS
  77.             (
  78.                 SELECT pm.* FROM {$wpdb->postmeta} pm
  79.                 WHERE p.ID = pm.post_id
  80.                 AND pm.meta_key = '%s'
  81.             )
  82.             AND p.post_type = '%s'
  83.             AND p.post_status = '%s'
  84.             ",
  85.             $meta_key,
  86.             $post_type,
  87.             $post_status
  88.         ) );
  89.    
  90.     return $result;
  91. }
  92. /*
  93.     Example - fetch posts with given meta, then pass to get_posts
  94.     -----------------
  95.     <?php
  96.     // Find posts without a meta entry for the fruit custom field
  97.     $posts_without_fruit = posts_without_meta( 'fruit', '', '', 'ids' );
  98.    
  99.     // If the result didn't come back false
  100.     if( $posts_without_fruit )
  101.    
  102.         // Pass the IDs returned into get_posts
  103.         $posts_without_meta = get_posts( 'include=' . implode( ',', $posts_without_fruit) );
  104.    
  105.     // Basic get_posts loop
  106.     foreach( $posts_without_meta as $post ) :
  107.         setup_postdata( $post );
  108.        
  109.         the_title();
  110.         echo '<br />';
  111.        
  112.     endforeach;
  113.    
  114.     wp_reset_query();
  115.     ?>
  116. */
  117. ?>
RAW Paste Data