Have a look to this
function get_posts_fields( $args = array() ) {
$valid_fields = array(
'ID'=>'%d', 'post_author'=>'%d',
'post_type'=>'%s', 'post_mime_type'=>'%s',
'post_title'=>false, 'post_name'=>'%s',
'post_date'=>'%s', 'post_modified'=>'%s',
'menu_order'=>'%d', 'post_parent'=>'%d',
'post_excerpt'=>false, 'post_content'=>false,
'post_status'=>'%s', 'comment_status'=>false, 'ping_status'=>false,
'to_ping'=>false, 'pinged'=>false, 'comment_count'=>'%d'
);
$defaults = array(
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'post_date',
'order' => 'DESC',
'posts_per_page' => get_option('posts_per_page'),
);
global $wpdb;
$args = wp_parse_args($args, $defaults);
$where = "";
foreach ( $valid_fields as $field => $can_query ) {
if ( isset($args[$field]) && $can_query ) {
if ( $where != "" ) $where .= " AND ";
$where .= $wpdb->prepare( $field . " = " . $can_query, $args[$field] );
}
}
if ( isset($args['search']) && is_string($args['search']) ) {
if ( $where != "" ) $where .= " AND ";
$where .= $wpdb->prepare("post_title LIKE %s", "%" . $args['search'] . "%");
}
if ( isset($args['include']) ) {
if ( is_string($args['include']) ) $args['include'] = explode(',', $args['include']);
if ( is_array($args['include']) ) {
$args['include'] = array_map('intval', $args['include']);
if ( $where != "" ) $where .= " OR ";
$where .= "ID IN (" . implode(',', $args['include'] ). ")";
}
}
if ( isset($args['exclude']) ) {
if ( is_string($args['exclude']) ) $args['exclude'] = explode(',', $args['exclude']);
if ( is_array($args['exclude']) ) {
$args['exclude'] = array_map('intval', $args['exclude']);
if ( $where != "" ) $where .= " AND ";
$where .= "ID NOT IN (" . implode(',', $args['exclude'] ). ")";
}
}
extract($args);
$iscol = false;
if ( isset($fields) ) {
if ( is_string($fields) ) $fields = explode(',', $fields);
if ( is_array($fields) ) {
$fields = array_intersect($fields, array_keys($valid_fields));
if( count($fields) == 1 ) $iscol = true;
$fields = implode(',', $fields);
}
}
if ( empty($fields) ) $fields = '*';
if ( ! in_array($orderby, $valid_fields) ) $orderby = 'post_date';
if ( ! in_array( strtoupper($order), array('ASC','DESC')) ) $order = 'DESC';
if ( ! intval($posts_per_page) && $posts_per_page != -1)
$posts_per_page = $defaults['posts_per_page'];
if ( $where == "" ) $where = "1";
$q = "SELECT $fields FROM $wpdb->posts WHERE " . $where;
$q .= " ORDER BY $orderby $order";
if ( $posts_per_page != -1) $q .= " LIMIT $posts_per_page";
return $iscol ? $wpdb->get_col($q) : $wpdb->get_results($q);
}
It's a function that mimics get_posts but with the ability to get the fields you desire. Be aware: this function is not get_posts and has 2 great limitations: run only in posts table so taxonomy and meta query cannot be run!
However, the query can rely on all the post fields and on some 'special' arguments like include, exclude and search.
The good part is this: the fields you are able to retrieve are all the field of the post table. Just pass a list or an array in the fields argument.
Bonus: passing only one field is returned a one dimensional array of strings or integers (instead of an array of objects).
List of Available args are:
$available_args = array(
'ID', // int
'post_author', // string
'post_type', // string
'post_mime_type', // string
'post_name', // string
'post_date', // string
'post_modified', // string
'menu_order', // int
'post_parent', // int
'post_status', // string
'comment_status', // string
'comment_count', // int
'orderby', // string, a valid field name
'order', // string 'ASC', or 'DESC',
'posts_per_page', // int
'include', // array (or comma separed string) of post ids
'exclude', // array (or comma separed string) of post ids
'search', // string if passed will search for it in post title
'fields', // array (or comma separed string) of fields to retrieve.
// If only 1 field is passed a 'flat' array is returned
);
Examples of usage
// Retrieve the date and the title of pages having 'Hello' in the title
$pages_hello = get_posts_fields("post_type=page&search=Hello&fields=post_date,post_title");
// another example
$args = array(
'post_type' => 'custom_post',
'posts_per_page' => -1,
'post_parent' => 1,
'include' => array(2,3,4),
'exclude' => '6,8,10',
'fields' => array('post_title', 'comment_status')
);
get_posts_fields($args);
// One more, just for fun ;)
$args = array(
'post_type' => 'attachment', 'posts_per_page' => -1,
'post_status' => 'inherit', 'fields' => 'post_mime_type'
);
foreach ( array_count_values ( get_posts_fields($args) ) as $mime => $count ) {
echo "I have $count media of the type $mime" . PHP_EOL;
}