WordPress: display archive links grouped by year

I’m currently using wp_get_archives('type=monthly') to display archive links in my sidebar. This is the output:

<ul>
    <li><a href='http://example.com/2011/08/'>August 2011</a></li>
    <li><a href='http://recently.se/2011/07/'>July 2011</a></li>
    <li><a href='http://recently.se/2010/12/'>December 2010</a></li>
</ul>

Is it possible to group the months by year instead? Something like this:

<ul>
    <h2>2011</h2>
    <li><a href='http://example.com/2011/08/'>August 2011</a></li>
    <li><a href='http://recently.se/2011/07/'>July 2011</a></li>

    <h2>2010</h2>
    <li><a href='http://recently.se/2010/12/'>December 2010</a></li>
</ul>

Related posts

Leave a Reply

1 comment

  1. This is how I implemented it, although I’m sure there’s a better way. I added these functions to my theme’s functions.php file:

    function twentyeleven_get_archives_callback($item, $index, $currYear) {
        global $wp_locale;
    
        if ( $item['year'] == $currYear ) {
            $url = get_month_link( $item['year'], $item['month'] );
            // translators: 1: month name, 2: 4-digit year
            $text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($item['month']), $item['year']);
            echo get_archives_link($url, $text);
        }
    }
    
    function twentyeleven_get_archives() {
        global $wpdb;
    
        $query = "SELECT YEAR(post_date) AS `year` FROM $wpdb->posts WHERE `post_type` = 'post' AND `post_status` = 'publish' GROUP BY `year` ORDER BY `year` DESC";
        $arcresults = $wpdb->get_results($query);
        $years = array();
    
        if ($arcresults) {
            foreach ( (array)$arcresults as $arcresult ) {
                array_push($years, $arcresult->year);
            }
        }
    
        $query = "SELECT YEAR(post_date) as `year`, MONTH(post_date) as `month` FROM $wpdb->posts WHERE `post_type` = 'post' AND `post_status` = 'publish' GROUP BY `year`, `month` ORDER BY `year` DESC, `month` ASC";
        $arcresults = $wpdb->get_results($query, ARRAY_A);
        $months = array();
    
        if ( $arcresults ) {
            foreach ($years as $year) {
                        //My Display
                //echo "t<li>ntt<a href="#">$year</a>ntt<ul>n";
                //array_walk($arcresults, "twentyeleven_get_archives_callback", $year);
                //echo "tt</ul>nt</li>n";
    
                        //Your Display
                echo "t<h2>$year</h2>nt<ul>n";
                array_walk($arcresults, "twentyeleven_get_archives_callback", $year);
                echo "t</ul>n";
            }
        }
    }
    

    You would call this function instead of wp_get_archives() in your theme like so:

    <ul>
    <?php twentyeleven_get_archives(); ?>
    </ul>
    

    The function names can be whatever you want, although good practice is to prefix them with your theme’s name (i.e. twentyeleven_)

    I referenced wp_get_archives() and get_archives_link() in wp-includes/general-template.php.