WordPress Wednesdays: Better Archive Lists in WordPress

In this week’s post, we show you how we modified Stem’s blog archives page to segment the monthly listing by year of publication, like on the Strategy Blog’s new archive page.

Jump ahead to see the complete code!

The eagle-eyed among you have probably noticed small tweaks to the Stem site and Strategy Blog this past week. As we gear down at the end of the year, I’m putting time towards minor tasks that have been sitting around forever, and one such change turned into a wacky solution I’d like to share.

Unlike the previous two WordPress Wednesdays, this week we’re getting into some PHP and WordPress template tweaking; there’s nothing too daunting here, but as usual, before making any changes to your WordPress theme, make sure you back everything up.

This particular solution all started with the Stem Strategy Blog. As the sidebar archives grew from two years when I started with Stem, to four (and with a fifth quickly creeping up) I decided it was time to reduce the sidebar list to just the last 12 months, and stash the rest of the links on a separate archive page.

Of course, the huge list didn’t look any more readable on a separate page than it did in the sidebar; I decided blocking the list out by year, and adding some headers would help make it more manageable. This is when I started running into problems. WordPress lists archives by using a function called wp_get_archives(); — unfortunately, the function just returns a bunch of HTML including the links to the archive pages, and whatever tags you’ve specified to surround each. You can set the archives to output as daily, weekly or monthly links, but you cannot limit the archives listed by year.

After a bit of searching online, I tracked down a great function for adding ‘year’ attribute to wp_get_archives, put together by Chris Smith:

Add this to your theme’s functions.php file:

function getarchives_filter($where, $args) {
if (isset($args['year'])) {
$where .= ' AND YEAR(post_date) = ' . intval($args['year']); }
return $where;
}
add_filter('getarchives_where', 'getarchives_filter', 10, 2);

Now you can specify a year in your archives, like so: wp_get_archives('type=monthly&year=2010');

This alone would allow me to set up each year with its own header and links. However, as soon as 2012 rolled around (and 2013… and 2014…) I would have to go in and edit this code. The next step is to automate the process: The following snippet gets the current year, and creates an array ranging from the current year, down to the first year of the blog — in this case, I hardcoded 2007, as that wouldn’t change:

$currentyear = date("Y");
$years = range($currentyear, 2007);

Using that information, I could run a foreach loop and output the year’s header and list of archives automatically, going from the current year, down to 2007:

<?php
$currentyear = date("Y");
$years = range($currentyear, 2007);
foreach($years as $year) { ?>

<h2><?php echo $year; ?></h2>
<ul>
<?php wp_get_archives('type=monthly&year='.$year); ?>
</ul>
<?php } ?>

Now we’re outputting each year’s worth of archives under its header… in reverse order. This seems to make sense in a sidebar, but seeing it under each year’s header just looked wrong. Unfortunately, there is also not an option to reverse the order when using the wp_get_archives() function. I tried next to save the value of wp_get_archive() in a variable and try to run a loop on my own, only to discover that the output of the function isn’t an array, but a string.

Thankfully, the developer and support community for WordPress is strong and active, and a solution to this problem was in the support forums. The following code ‘explodes’ the wp_get_archives(); string, and loops through it to store it in an array called $links[]:

//get the archives as per usual
//making sure not to output them by using 'echo=0'
$archi = wp_get_archives( 'echo=0&type=monthly&year='.$year );

//split the archives into an array
//using the </li> tags
$archi = explode( '</li>' , $archi );

$links = array();

//using the <li> tags, loop through the $archi array,
//cleaning up the rest of the extra HTML,
//and storing the output in the $links[] array

foreach( $archi as $link ) {
$link = str_replace( array( '<li>' , "\n" , "\t" , "\s" ), '' , $link );
if( '' != $link )
$links[] = $link;
else
continue;
}

Last but not least, reverse the order of the array, like so:

$fliplinks = array_reverse($links);

… output them to the page…

<ul>
<?php
foreach( $fliplinks as $link ) {
echo '<li>'.$link.'</li>';
} ?>
</ul>

… and you’ve got yourself a categorized archive page!


The Complete Code

The code for this nifty trick, in its entirety, is as follows — don’t forget to back up your theme files before making any changes!

For your theme’s functions.php file:

function getarchives_filter($where, $args) {
if (isset($args['year'])) {
$where .= ' AND YEAR(post_date) = ' . intval($args['year']);
}
return $where;
}
add_filter('getarchives_where', 'getarchives_filter', 10, 2);

And in the template used on your static archive page:

<?php
$currentyear = date("Y");
$years = range($currentyear, 2007);
foreach($years as $year) { ?>

<h2><?php echo $year; ?></h2>

<ul>

<?php
$archi = wp_get_archives( 'echo=0&type=monthly&year='.$year );
$archi = explode( '</li>' , $archi );
$links = array();

foreach( $archi as $link ) {
$link = str_replace( array( '<li>' , "\n" , "\t" , "\s" ), '' , $link );
if( '' != $link )
$links[] = $link;
else
continue;
}

$fliplinks = array_reverse($links);

foreach( $fliplinks as $link ) {
echo '<li>'.$link.'</li>';
}
?>
</ul>

You can see the finished product on the new archive page — the implementation right now is pretty simple; if you try this out on your own site, please share what you come up with below!

Comments are closed.

Legal FAQ Collections