This is a function I made to use for general needs, to retrieve post or custom post types data before or after a certain year/month, or current year, in whichever order you need:
// you could change the name in case it collides with some other plugin
function get_posts_by_date($user_options = array()){
$options = array(
'year_limit' => '1980'
,'month_limit' => '01'
,'operator' => '>=' // date comparison operator
,'current_year' => true // limit data to current year
,'post_type' => 'post'
,'year_order' => 'DESC'
,'month_order' => 'DESC'
,'post_ids_order' => 'DESC'
,'raw_output' => false
);
extract(array_merge($options, $user_options));
global $wpdb;
if($operator == '>=' || $operator == '=='){
$day = "01";
} elseif($mode == '<='){
$day = "31";
}
if($current_year){ // will be after [previous year]/12/31
$year_limit = date('Y', strtotime('-1 year'));
$month_limit = '12';
$day = "31";
$operator == '>=';
}
// warning: if your parameters come from user input/forms,
// pass them using $wpdb::prepare()
// https://developer.wordpress.org/reference/classes/wpdb/prepare/
$results = $wpdb->get_results("
SELECT tbl.y year, group_concat(month_posts ORDER BY tbl.m " . $month_order . " SEPARATOR '-') months
FROM (
SELECT YEAR(p.post_date) y, MONTH(p.post_date) m, concat(MONTH(p.post_date), ':', group_concat(p.id ORDER BY p.post_date " . $post_ids_order . " )) month_posts
FROM $wpdb->posts p
WHERE (p.post_status = 'publish' OR p.post_status = 'future')
AND p.post_type = '" . $post_type . "'
AND p.post_date " . $operator . " DATE('" . $year_limit . "-" . $month_limit . "-" . $day . " 00:00:00')
GROUP BY y, m
) tbl
GROUP BY tbl.y
ORDER BY tbl.y " . $year_order
);
if($raw_output) return $results;
global $wp_locale;
foreach ($results as $data){
$months_data = explode('-',$data->months);
$months = array();
$data->count = 0; // year count
foreach ($months_data as $month_data){
$month_obj = new stdClass;
$splitted = explode(':',$month_data);
$raw_month = $splitted[0];
$month_obj->number = $raw_month;
$month_obj->name = $wp_locale->get_month($raw_month);
$month_obj->posts = array();
$post_ids = explode(',',$splitted[1]);
$data->count += count($post_ids);
foreach($post_ids as $post_id){
$month_obj->posts[] = get_post($post_id);
$months[$raw_month] = $month_obj;
}// foreach
}// foreach
$data->months = $months;
}// foreach
return $results;
}// get_posts_by_date
Usage example:
$posts_by_date = get_posts_by_date(array(
'year_limit' => '2016'
,'operator' => '<='
,'current_year' => false
,'post_type' => 'product'
,'month_order' => 'ASC'
,'raw_output' => true
));
If raw_output
option is true, the default output will be something like this:
array(2) {
[0]=>
object(stdClass)#6645 (2) {
["year"]=>
string(4) "2017"
["months"]=>
string(65) "8:386,401-7:406,373,380,377,408,399,362-6:1,391,404-5:367,397,394"
}
[1]=>
object(stdClass)#6644 (2) {
["year"]=>
string(4) "2016"
["months"]=>
string(5) "6:429"
}
}
The "months" string contains values formatted as:
month:[post ids]-month:[post ids]-ecc
If raw_output
option is false, you get a list of posts like this:
array (array of objects)
object
-> year (ex. '2017')
-> count (total year's posts)
-> months (array of objects)
month
-> number (of month)
-> name (localized)
-> posts (array of post objects)
Happy coding... :)
query_posts