Custom postal type per year / month

I have custom news posts on my Wordpress site. I use the Advanced Custom Fields plugin to add metadata to each post.

I want to create an array of news as an archive:

[2013] [January] => 5 [2012] [January] => 20 [February] => 10 [2011] [April] => 30 

I managed to get this working using:

  global $wpdb; $news = $wpdb->get_results( "SELECT wp_posts.post_date, COUNT(wp_posts.ID) as count FROM $wpdb->posts WHERE wp_posts.post_type = 'news' AND wp_posts.post_status = 'publish' AND wp_posts.post_date <= CURDATE() AND wp_posts.post_date >= DATE_SUB(CURDATE(), INTERVAL 3 YEAR) GROUP BY YEAR(wp_posts.post_date), MONTH(wp_posts.post_date) ORDER BY wp_posts.post_date DESC", ARRAY_A); $archive = array(); foreach ($news as $post): $year = date('Y', strtotime($post['post_date'])); $month = date('m', strtotime($post['post_date'])); $month_name = date('F', strtotime($post['post_date'])); $post['url'] = 'NOT SURE ABOUT URL'; $archive[$year][$month_name] = $post; endforeach; 

I need to be able to link to specific years and months using http://example.com/2012/ and http://example.com/2012/10/ .

How does this relate to personalized news messages, I'm not sure how to do this?

+6
source share
2 answers

To accomplish what you need, you need to modify Wordpress rewrites to be able to capture year / month / etc data for a personalized message type.

You can do this with the following code:

 /** * Custom post type date archives */ /** * Custom post type specific rewrite rules * @return wp_rewrite Rewrite rules handled by Wordpress */ function cpt_rewrite_rules($wp_rewrite) { $rules = cpt_generate_date_archives('news', $wp_rewrite); $wp_rewrite->rules = $rules + $wp_rewrite->rules; return $wp_rewrite; } add_action('generate_rewrite_rules', 'cpt_rewrite_rules'); /** * Generate date archive rewrite rules for a given custom post type * @param string $cpt slug of the custom post type * @return rules returns a set of rewrite rules for Wordpress to handle */ function cpt_generate_date_archives($cpt, $wp_rewrite) { $rules = array(); $post_type = get_post_type_object($cpt); $slug_archive = $post_type->has_archive; if ($slug_archive === false) return $rules; if ($slug_archive === true) { $slug_archive = $post_type->name; } $dates = array( array( 'rule' => "([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})", 'vars' => array('year', 'monthnum', 'day')), array( 'rule' => "([0-9]{4})/([0-9]{1,2})", 'vars' => array('year', 'monthnum')), array( 'rule' => "([0-9]{4})", 'vars' => array('year')) ); foreach ($dates as $data) { $query = 'index.php?post_type='.$cpt; $rule = $slug_archive.'/'.$data['rule']; $i = 1; foreach ($data['vars'] as $var) { $query.= '&'.$var.'='.$wp_rewrite->preg_index($i); $i++; } $rules[$rule."/?$"] = $query; $rules[$rule."/feed/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i); $rules[$rule."/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i); $rules[$rule."/page/([0-9]{1,})/?$"] = $query."&paged=".$wp_rewrite->preg_index($i); } return $rules; } 

You will notice that I have hard-coded news in $rules = cpt_generate_date_archives('news', $wp_rewrite); parts of the code. You can change this as needed.

With this code, you can go to http://yoursite.com/news/2013/02/ and get a list of archives for this particular type of message for that particular time.

For completeness, I'll tell you how to create a monthly archive widget to use this.

 /** * Get a montlhy archive list for a custom post type * @param string $cpt Slug of the custom post type * @param boolean $echo Whether to echo the output * @return array Return the output as an array to be parsed on the template level */ function get_cpt_archives( $cpt, $echo = false ) { global $wpdb; $sql = $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_type = %s AND post_status = 'publish' GROUP BY YEAR($wpdb->posts.post_date), MONTH($wpdb->posts.post_date) ORDER BY $wpdb->posts.post_date DESC", $cpt); $results = $wpdb->get_results($sql); if ( $results ) { $archive = array(); foreach ($results as $r) { $year = date('Y', strtotime( $r->post_date ) ); $month = date('F', strtotime( $r->post_date ) ); $month_num = date('m', strtotime( $r->post_date ) ); $link = get_bloginfo('siteurl') . '/' . $cpt . '/' . $year . '/' . $month_num; $this_archive = array( 'month' => $month, 'year' => $year, 'link' => $link ); array_push( $archive, $this_archive ); } if( !$echo ) return $archive; foreach( $archive as $a ) { echo '<li><a href="' . $a['link'] . '">' . $a['month'] . ' ' . $a['year'] . '</a></li>'; } } return false; } 

To use this function, simply put the pool of a custom message type, that is: get_cpt_archives( 'news' ) . This will return an array of unique Year / Dates / Links, i.e.:

 Array ( [0] => Array ( [month] => February [year] => 2013 [link] => http://yoursite.com/news/2013/02 ) [1] => Array ( [month] => January [year] => 2013 [link] => http://yoursite.com/news/2013/01 ) ) 

You can skip them using foreach and output them foreach you want.

Alternatively, you can use get_cpt_archives( 'news', true ) , which automatically sounders every element enclosed in a <li> link associated with its specific archive.

Formatting the output is not exactly what you wanted, so you will have to tweak it a bit to display it in

 Year Month Month Year Month 

which you need.

Hope this helps.

+26
source

I know this is an old post, but there is a much more concise way of doing what the OP asks for:

 function cpt_add_rewrite_rules() { $cpt = 'news'; add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})?$', 'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]&day=$matches[3]', 'top'); add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})?$', 'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]', 'top'); add_rewrite_rule($cpt.'/([0-9]{4})?$', 'index.php?post_type='.$cpt.'&year=$matches[1]', 'top'); } add_filter('init', 'cpt_add_rewrite_rules'); 
+3
source

All Articles