Custom WordPress loop to show only posts within a certain timeframe

A client wanted to display the most recent news item (i.e. blog post) on their homepage sidebar. Simple enough to do with a custom loop. It’s not a super active industry though, so there can be long periods between news items being posted. So rather than keeping old news on the homepage for long periods of time, they wanted a way for the post to disappear from the homepage after a set period of time (say, one month), but still appear in their News archives.

One solution I thought of was to create a tag (e.g. ‘featured’), then create a custom WordPress loop that shows only posts with that tag on the homepage:

<?php
     // Query posts tagged 'featured'
     query_posts( 'tag=featured' );

     // The Loop
     if (have_posts()) : while ( have_posts() ) : the_post();
          echo '<h3>Recent News</h3>';
          echo '<li>';
          echo '<a href="';
          the_permalink();
          echo '">';
          the_title();
          echo '</a>';
          echo '</li>';
          endwhile; endif;
          // Reset Query
          wp_reset_query();
?>

 

After a month the client could then edit the post to delete the tag and remove the post from the homepage.

That works, but it requires remembering to add the ‘featured’ tag when the post is first published, and then take the extra step of logging in and deleting the tag later. This solution is not ideal.

Instead, I wanted to find a way to make it disappear from the homepage automatically. And while we’re at it, I also wanted the “Recent News” heading to disappear when there are no posts to display.

I found a tutorial on WP Recipes showing how to achieve this with custom fields. Basically, create a custom field with a key of ‘expiration’ and a value with the date/time format mm/dd/yyyy 00:00:00 that you would use to fill in the expiry date.

This solution would work just fine for a nerd like me, but it’s too technical for my client. I wanted them to be able to just hit publish and not have to think about it again.

After much searching and forum discussions I finally figured it out. I found lots of helpful advice from literally dozens of sources, but the two main sources that led me to this solution are the WordPress codex and this thread on the WordPress forums.

First, I created a filter before the custom loop telling WordPress to query posts published within the last 30 days:

function filter_where($where = '') {
     $where .= " AND post_date > '" . date('Y-m-d', strtotime('-30 days')) . "'";
     return $where;
     }
add_filter('posts_where', 'filter_where');

Then I set up the query_posts to show only one post:

query_posts( 'posts_per_page=1' );

If there are any posts to show, the ‘Recent News’ heading and the title of the post embedded in the permalink are displayed. If there are no posts matching the query, nothing is displayed.

if (have_posts()) : while ( have_posts() ) : the_post();
     echo '<h3>Recent News</h3>';
     echo '<li>';
     echo '<a href="';
     the_permalink();
     echo '">';
     the_title();
     echo '</a>';
     echo '</li>';
endwhile; endif;

(By the way, I’m not 100% happy with where I’ve placed the ‘Recent News’ heading. If more than one post is ever displayed the heading would appear above every post title. It’s not a problem right now since the client only plans to show one post at a time. But I’m going to look for a solution to ensure that multiple posts can be displayed without repeating the header. Once I find that solution I’ll post it here.)

Next, the filter is removed:

remove_filter('posts_where', 'filter_where');

And finally the query is reset so it doesn’t interfere with any other queries:

wp_reset_query();

The complete custom WordPress loop looks like this:

<?php
     function filter_where($where = '') {
     //only show posts published within the last 30 days
     $where .= " AND post_date > '" . date('Y-m-d', strtotime('-30 days')) . "'";
     return $where;
     }
     add_filter('posts_where', 'filter_where');

     // Query posts
     query_posts( 'posts_per_page=1' );

     // The Loop
     if (have_posts()) : while ( have_posts() ) : the_post();
     echo '<h3>Recent News</h3>';
     echo '<li>';
     echo '<a href="';
     the_permalink();
     echo '">';
     the_title();
     echo '</a>';
     echo '</li>';
     endwhile; endif;

     //remove the filter
     remove_filter('posts_where', 'filter_where');

     // Reset Query
     wp_reset_query();
?>

So far that appears to have taken care of it. Admittedly, I’m still learning PHP, so if any readers have a better way to do this or want to tell me I’ve done something horrendously wrong I’d love to hear about it in the comments.

Leave a Reply

Your email address will not be published. Required fields are marked *