Search code examples
phpwordpresslistdatearchive

Year and Month in Wordpress Archive List


I'd like to list all years from which there are public Wordpress posts, and in a sub-menu below, the months from those years. Example:

  • 2016
    • August
    • March
  • 2015
    • June
    • May
    • February

I have a working version of this inside a loop, but it requires me to manually add a new list every year. Is there any way to adjust it, so that it includes the new year automatically?

<h1>2016</h1>
<ul>
     <?php
$string = wp_get_archives('type=monthly&year=2016&echo=0');
$pattern = ' ((19|20)\d{2}(</a>))';
echo preg_replace($pattern, '\\3', $string); '<li></li>';?>
</ul></a>
<h1>2015</h1>
 <?php
$string = wp_get_archives('type=monthly&year=2015&echo=0');
$pattern = ' ((19|20)\d{2}(</a>))';
echo preg_replace($pattern, '\\3', $string); '<li></li>';?>
</ul></a>

Solution

  • Ok, found a very helpful post on stack exchange: here

    Basically, add this to functions.php:

    //List archives by year, then month
    function wp_custom_archive($args = '') {
        global $wpdb, $wp_locale;
    
        $defaults = array(
            'limit' => '',
            'format' => 'html', 'before' => '',
            'after' => '', 'show_post_count' => false,
            'echo' => 1
        );
    
        $r = wp_parse_args( $args, $defaults );
        extract( $r, EXTR_SKIP );
    
        if ( '' != $limit ) {
            $limit = absint($limit);
            $limit = ' LIMIT '.$limit;
        }
    
        // over-ride general date format ? 0 = no: use the date format set in Options, 1 = yes: over-ride
        $archive_date_format_over_ride = 0;
    
        // options for daily archive (only if you over-ride the general date format)
        $archive_day_date_format = 'Y/m/d';
    
        // options for weekly archive (only if you over-ride the general date format)
        $archive_week_start_date_format = 'Y/m/d';
        $archive_week_end_date_format   = 'Y/m/d';
    
        if ( !$archive_date_format_over_ride ) {
            $archive_day_date_format = get_option('date_format');
            $archive_week_start_date_format = get_option('date_format');
            $archive_week_end_date_format = get_option('date_format');
        }
    
        //filters
        $where = apply_filters('customarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );
        $join = apply_filters('customarchives_join', "", $r);
    
        $output = '<ul>';
    
            $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC $limit";
            $key = md5($query);
            $cache = wp_cache_get( 'wp_custom_archive' , 'general');
            if ( !isset( $cache[ $key ] ) ) {
                $arcresults = $wpdb->get_results($query);
                $cache[ $key ] = $arcresults;
                wp_cache_set( 'wp_custom_archive', $cache, 'general' );
            } else {
                $arcresults = $cache[ $key ];
            }
            if ( $arcresults ) {
                $afterafter = $after;
                foreach ( (array) $arcresults as $arcresult ) {
                    $url = get_month_link( $arcresult->year, $arcresult->month );
                    $year_url = get_year_link($arcresult->year);
                    /* translators: 1: month name, 2: 4-digit year */
                    $text = sprintf(__('%s'), $wp_locale->get_month($arcresult->month));
                    $year_text = sprintf('%d', $arcresult->year);
                    if ( $show_post_count )
                        $after = '&nbsp;('.$arcresult->posts.')' . $afterafter;
                    $year_output = get_archives_link($year_url, $year_text, $format, $before, $after);              
                    $output .= ( $arcresult->year != $temp_year ) ? $year_output : '';
                    $output .= get_archives_link($url, $text, $format, $before, $after);
    
                    $temp_year = $arcresult->year;
                }
            }
    
        $output .= '</ul>';
    
        if ( $echo )
            echo $output;
        else
            return $output;
    }
    

    And then call this function on the page:

    <?php wp_custom_archive(); ?>
    

    It will return a list exactly as needed, by year then month, with links to each!