WordPress – Display A List Of Latest Posts But Exclude Sticky Posts

Today I finally found a solution to a problem that has been bugging me for years. In WordPress, by default, lists of your latest posts display, as you can probably imagine, your latest posts. However, if you chose to make a post “sticky”, i.e. request that it appears at the top of your homepage, category pages and tag pages, it will also appear at the top of the recent / latest posts. By the time you have made 4-5 posts sticky (e.g. one of each of 5 different categories) your latest posts lists become eternally stuck in the past.

My workaround for a while was to first not make any posts sticky, and then later to restrict it to 3 posts and then display 8 “latest posts”, so that 5 new ones always show across the site. This still sucked a bit though as it meant that any regular readers will see the same top 3 posts (the stickies) and think that I have not published anything new.

The Solution

If there was a plugin I would have used it, but nobody else seems bothered enough about this to make one. So this is what you do.

If you list your latest posts in a text widget in the sidebar, download one of the plugins that allow PHP in text widgets. I use PHP Text Widget by Stefano Lissa. It is very simple, you just install it and then leave it. From then on PHP works in the standard WordPress text widgets. Some plugins provide a special widget for PHP, but I prefer this method.

Then, in your widget, throw in some code like this:

<h2>New Posts</h2>

<?php
$args = array(
‘category__in’ => array(),
‘showposts’ => 7,
‘post__not_in’ => get_option(‘sticky_posts’),
‘caller_get_posts’=>1
);

$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {

while ($my_query->have_posts()) : $my_query->the_post(); ?>
<p><a href=”<?php the_permalink() ?>” rel=”bookmark” title=”Permanent Link to <?php the_title_attribute(); ?>”><?php the_title(); ?></a></p>
<?php
endwhile;
} //if ($my_query)
wp_reset_query(); // Restore global post data stomped by the_post().
?>

The bit in bold is the clever bit. Do not ask me to explain it, I “discovered” the solution after a hell of a lot of Googling. Been searching on and off for nigh on a year now. Many conversations about this were simply not relevant to what I needed.

So, Who Did Provide the Solution?

The solution was posted on to the WordPress support forums 2 years ago by MichaelH, one of the official volunteers. His code was actually like this:

<?php
$args = array(
‘category__in’ => array(14),
‘showposts’ => 10,
‘post__not_in’ => get_option(‘sticky_posts’),
‘caller_get_posts’=>1
);

$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {
echo ’10 recent Posts for Category 14, excludes sticky posts’;
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<p><small><?php the_time(‘m.d.y’) ?></small> <a href=”<?php the_permalink() ?>” rel=”bookmark” title=”Permanent Link to <?php the_title_attribute(); ?>”><?php the_title(); ?></a></p>
<?php
endwhile;
} //if ($my_query)
wp_reset_query(); // Restore global post data stomped by the_post().
?>

However, this puts a small date in front of each listing. It is also for a specific category, not for all categories. You can find the whole conversation here: http://wordpress.org/support/topic/exclude-sticky-posts-from-query

So, there you go. Have a real list of latest blog posts, even when you also have many sticky posts.