All I want is an array of years that posts exist from first to last but for some reason I'm only getting the first two years, 2019 and 2018, when I have posts going back to 2016. Here's my code:

 <ul class="inline-list posts-by--year">
            <li>Posts by year:</li>
            <li><a href="<?php echo get_site_url(); ?>/news-and-media">All Posts</a></li>
$terms_year = array(
    'post_type' => array('post'),

$years = array();
$query_year = new WP_Query($terms_year);

if ($query_year->have_posts()):
    while ($query_year->have_posts()): $query_year->the_post();
        $year = get_the_date('Y');
        if (!in_array($year, $years)) {
            $years[] = $year;
            echo '<li><a href="';
            echo home_url();
            echo '/news-and-media/?year=';
            echo $year;
            echo '">';
            echo $year;
            echo '</a></li>';

It works when I do this, but was hoping to use the ?year= filter instead of archive:

<ul class="inline-list posts-by--year">
            <li>Posts by year:</li>
            <li><a href="<?php echo get_site_url(); ?>/news-and-media">All Posts</a></li>
<?php $args = array(
    'type'            => 'yearly',
    'limit'           => '',
    'format'          => 'custom', 
    'before'          => '<li class="nothing">',
    'after'           => '</li>',
    'show_post_count' => false,
    'echo'            => 1,
    'order'           => 'DESC',
    'post_type'     => 'post'
wp_get_archives( $args ); 


1 Answer 1


I am not sure why you prefer the longer method over wp_get_archives(). I recommend letting Wordpress do the work for you. It is more efficient, and easier to read.

However ... since you presented a particular preference:

It would appear that you are using an array for post_type, when none is required. Try modifying your WP_Query args to:

$terms_year = array(
    'post_type' => 'post',
    'orderby'   => 'modified',
    'order' => 'DESC',
    'post_status' => 'publish',

This will pre-order your entries, so all posts of a particular year appear at one time. Also, adding post_status ensures you don't end up with revisions,drafts, or trash that the public would never see.

Then, for readability, I might build your <li> output like this:

if (!array_key_exists($year, $years)) {
       $years[$year] = '<li><a href="';
       $years[$year] .=  home_url();
       $years[$year] .=  '/news-and-media/?year=';
       $years[$year] .=  $year . '">';
       $years[$year] .=  $year;
       $years[$year] .=  '</a></li>';
       echo $years[$year];

Echo statements are costly to performance. So, you are much better off building your full string, then echo it. And .. this is just much easier to read.

One final (unsolicited) critique ... you should consider using either "home_url()" or "get_site_url()", not both. You have mixed them in this code sample. It may work, but it could cause trouble for you.

Hope this is helpful!

  • This is awesome thank you and for sure I don't want to use both home_url and get_site_url. I've decided to not be a wuss and use Archive loop; I just didn't want to update my archive template but that took about 2 seconds to do (used my blog template for its layout so they are both consistent). Commented Aug 24, 2019 at 1:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.